Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: CI
on:
pull_request:
push:
branches: [main, rack]
branches: [main, rack, "release/**"]
permissions:
contents: read
jobs:
Expand Down
80 changes: 80 additions & 0 deletions .github/workflows/install-path.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# The install-path test: LSDub in a clean ComfyUI the way a user gets it (ComfyUI's requirements + requirements.txt, no dev
# extras), CPU only. Every LSDub node registers; Align with aligner ctc from an empty models folder (the real recogniser
# download); a Dub at defaults; a Dub with the mouth Combos. scripts/install_path_check.py does the work; it runs the same on a
# laptop. publish.yml calls this workflow first, so a tag that fails it is never published.
name: Install path
on:
pull_request:
branches: [main]
push:
branches: ["release/**"] # scripts/release.py waits for this run before it tags
workflow_dispatch:
workflow_call:
schedule:
- cron: "17 6 * * 1" # weekly: ComfyUI's pin stays put, but PyPI and the Hub do not
permissions:
contents: read
concurrency:
group: install-path-${{ github.ref }}
cancel-in-progress: true
env:
COMFYUI_REPO: https://github.com/comfyanonymous/ComfyUI.git
COMFYUI_COMMIT: 355cd6b14c92c19ac3188fe528e47a3f21ef5178 # v0.42.0
RECOGNISER_REVISION: ae45363bf3413b374fecd9dc8bc1df0e24c3b7f4 # facebook/wav2vec2-lv-60-espeak-cv-ft, as lsdub_engine/_models.py pins it
# only used if scripts/fetch_demo.py itself fails (that still fails the job): the released v0.1.0 demo zip at its real checksum
DEMO_FALLBACK_URL: https://github.com/HumanjavaEnterprises/comfyui-lsdub/releases/download/v0.1.0/lsdub-demo-0.1.0.zip
DEMO_FALLBACK_SHA: 7981fef8f453b0bf29e47b3ffc00b3adcba1d22d8dbe259504f66c2beb00de17
jobs:
install-path:
runs-on: ubuntu-latest
timeout-minutes: 150
steps:
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
with:
path: pack
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
with:
python-version: "3.12"
- name: System deps (what the README asks a user for)
run: sudo apt-get update && sudo apt-get install -y ffmpeg libgles2 libegl1
- name: The pinned recogniser revision is the one the pack pins
run: grep -q "$RECOGNISER_REVISION" pack/lsdub_engine/_models.py
- name: ComfyUI at the pinned commit
run: |
git init -q comfy && cd comfy
git fetch -q --depth 1 "$COMFYUI_REPO" "$COMFYUI_COMMIT" && git checkout -q FETCH_HEAD
- name: A user's venv (ComfyUI requirements + requirements.txt, CPU torch)
run: |
python -m venv venv
venv/bin/pip install -q --upgrade pip
venv/bin/pip install -q torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu
venv/bin/pip install -q -r comfy/requirements.txt -r pack/requirements.txt
venv/bin/pip freeze | grep -iE '^(torch|transformers|huggingface.hub|mediapipe|numpy|phonemizer)=' || true
if venv/bin/python -c "import phonemizer" 2>/dev/null; then echo "::error::phonemizer is installed; the test needs a venv without it"; exit 1; fi
- name: Recogniser cache (fetched from the Hub once per revision, then served to the same client path)
id: hfcache
uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: hf-mirror
key: lsdub-recogniser-${{ env.RECOGNISER_REVISION }}
- name: Demo fallback zip
run: curl -sSfL -o demo-fallback.zip "$DEMO_FALLBACK_URL"
- name: Install path (nodes, align ctc from empty, dub at defaults, dub with the mouth Combos)
run: |
venv/bin/python pack/scripts/install_path_check.py --comfyui comfy --pack pack \
--hf-mirror hf-mirror --save-mirror hf-mirror \
--demo-fallback demo-fallback.zip --demo-fallback-sha "$DEMO_FALLBACK_SHA"
- name: "Save the recogniser cache (also when another step failed; the files are checked by sha256 either way)"
if: always() && steps.hfcache.outputs.cache-hit != 'true' && hashFiles('hf-mirror/pytorch_model.bin') != ''
uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: hf-mirror
key: lsdub-recogniser-${{ env.RECOGNISER_REVISION }}
- name: ComfyUI log
if: always()
run: tail -n 300 comfy/install-path-comfyui.log || true
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
if: failure()
with:
name: install-path-log
path: comfy/install-path-comfyui.log
4 changes: 4 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ on:
permissions:
contents: read
jobs:
install-path: # the gate: a tag whose tree fails the clean-ComfyUI install test is never published
if: github.repository == 'HumanjavaEnterprises/comfyui-lsdub'
uses: ./.github/workflows/install-path.yml
publish:
needs: install-path
runs-on: ubuntu-latest
if: github.repository == 'HumanjavaEnterprises/comfyui-lsdub'
steps:
Expand Down
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# Changelog

## 0.3.0 (2026-11-09)

- The new mouth is now the default, on the shipped demo face too; set the switches to classic for 0.2.x output (Mouth Tweaks' five mouth switches and Align's `aligner`).
- Verify's bands now read the mouth against the vocal: PASS needs clearly more sung syllables met than chance, the p/b/m shut and no extra shuts.
- On 190 test shots against 0.1.11: syllables met 0.54 → 0.72, p/b/m shut 0.27 → 0.55, vowel opening 0.89 → 0.97, stray shuts 2 → 0.
- Verify PASS on those shots: 0.1.11 8, the new mouth 59, the 1140 controls 0. The stricter target is shown beside it.
- New Mouth Tweaks switch `warp_realise`; Align now defaults to `ctc` (downloads 1.2 GB on first use).
- Workflows saved with 0.2.x values still load and keep the 0.2.x mouth.

Full changelog: https://lsdub.sndbnch.app/changelog

## 0.2.2 (2026-11-09)

- Fixed: LSDub Dub renders again with the new mouth switches on (0.2.1 failed every shot there).
Expand Down
39 changes: 39 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,42 @@ By contributing you agree your work is licensed under the Apache License 2.0, th
- No `## Unreleased` heading in the file; add the section when the version is released.
- The heading names the version in pyproject.toml. `python scripts/release_notes.py` checks all of this; CI runs it
(`tests/test_release_notes.py`) and the publish job fails without it.

## Stability policy
- Releases are batched; patch versions only for breakage. Features go into the next minor version.
- Defaults stay unchanged within a minor series unless the changelog says otherwise.
- Every release passes the install-path test (`.github/workflows/install-path.yml`, `scripts/install_path_check.py`) on a
clean ComfyUI before it is tagged. Run it yourself: `python scripts/install_path_check.py --comfyui PATH/TO/ComfyUI` with
that ComfyUI's venv (its requirements plus `requirements.txt`, nothing else).
- Models are pinned by revision and sha256.
- 0.2.0 to 0.2.2 landed in one day while the install-path test did not yet exist; it runs on every release from 0.2.3 on.

## Releases (maintainers)
One command, from a clean pack checkout on main with the engine and the microsite checked out beside it:

python scripts/release.py X.Y.Z --dry-run # every check, in a throwaway worktree; pushes nothing
python scripts/release.py X.Y.Z

Before it: write the `## X.Y.Z` section in CHANGELOG.md (see Release notes) and the matching `<section id="vX.Y.Z">` in the
microsite's `docs/changelog.html` on its main. The command refuses unless both trees are clean and on main and engine CI is
green; bumps the version, the Icon/Banner URLs and CITATION.cff; regenerates the node tables and the bug form; vendors the
engine; runs the pack checks; pushes `release/X.Y.Z` and waits for CI and Install path; then fast-forwards main, tags `vX.Y.Z`,
watches the publish (which runs Install path again first), confirms the Registry lists the version, then deploys the site
from your box: a clean microsite checkout on main, equal to origin/main, through wrangler's own login (`npx wrangler login`
once, account fa095a45453409a42f1c739a174e609f; an exported `CLOUDFLARE_API_TOKEN` is ignored), and checks that
https://lsdub.sndbnch.app/changelog answers 200 with the new version. To deploy the site by hand: from the microsite's clean
main, `env -u CLOUDFLARE_API_TOKEN CLOUDFLARE_ACCOUNT_ID=fa095a45453409a42f1c739a174e609f npx wrangler deploy`. Any failure before the tag stops with a plain message and leaves nothing changed remotely.

If release.py stops part way:
- Before "push release/X.Y.Z": nothing remote changed. Fix the cause; delete the local `release/X.Y.Z` branch
(`git checkout main && git branch -D release/X.Y.Z`) and drop a local engine record commit if one was made
(`git -C ../lsdub reset --hard origin/main`), then run it again.
- After the release branch is pushed but before the tag: only `release/X.Y.Z` is on origin. Fix on that branch and push
again (release.py waits on the new commit), or delete it (`git push origin --delete release/X.Y.Z`) and start over.
- After the tag: main and `vX.Y.Z` were pushed together (`--atomic`), so publish is running. Never re-tag or delete the tag;
watch the publish run, and if it failed, fix and release the next patch version. Push the engine record by hand if
release.py stopped before it did (`git -C ../lsdub push origin main`).
release.py names what it already pushed whenever it stops.

Repository secrets: only `REGISTRY_ACCESS_TOKEN` (here), the Comfy Registry publisher key, already set. The site needs no
secret: it deploys from the maintainer's box (above), the one deploy path.
28 changes: 26 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,10 @@ and `LSDub/qa`.
- `coherence_charge` (`remade`): the continuity repair's budget counts only the frames it re-makes. `all` is 0.1.9's,
which counts every flagged run.
- Set all three to their second choice to dub as 0.1.9 did.
- The vocal-driven mouth (default since 0.3.0): `warp_events` (`vocal`), `warp_hold` (`nucleus-follow`), `warp_closures`
(`aligned-press`), `warp_aperture` (`p95`) and `warp_realise` (`events`): one opening per sung syllable, lips shut only on
the lyric's p/b/m, vowels as wide as the singer's own. Set all five to `classic`, and Align's `aligner` to `classic`, for
the 0.2.x mouth.
- **LSDub Dub:** dubs each DUB and DUB-MEDIUM shot.
- The shot is cropped to a 512 px face and warped at 2x the frame rate. The lower face is pasted back and a measured
sync gate is applied.
Expand All @@ -169,6 +173,9 @@ and `LSDub/qa`.
**QA**
- **LSDub Verify:** a likely-success score per dubbed shot (PASS, REVIEW or FAIL), compared with the source. A soft or
held line is judged against the mouth travel the song asks for, and the report shows that reading beside the travel.
A shot can PASS when its mouth opens on clearly more of the sung syllables than chance would give, shuts on the sung
p/b/m and shuts nowhere else more often than the singer's own take (needs the recogniser Align `ctc` downloads; without
it, the 0.2.x band).
- **LSDub Scorecard:** every shot of the cut scored 0 to 100, worst first.
- **LSDub Sync QA:** the measured mouth against the vocal (correlation and lag), with a review card that scrolls the
vocal waveform past a playhead.
Expand Down Expand Up @@ -202,12 +209,29 @@ Python SDK (`pip install comfy-sdk`).
Qwen-Image-Edit Lightning LoRA).
- **Cost:** cloud runs use your Comfy credits.

## Stability and releases
LSDub aims to be stable software that is easy to install and build on, not a stream of updates.

- Releases are batched. A patch version (0.2.x) only fixes breakage; new features wait for the next minor version.
- Within a minor series the defaults stay unchanged unless the changelog says otherwise.
- 0.3.0 changed the defaults (the new mouth, Align `ctc`, Verify's bands), which is why it is a minor release.
- Every release passes the install-path test before it is tagged: a clean ComfyUI on CPU, only this pack's
requirements, every node registered, the phone recogniser downloaded into an empty models folder, and a Dub at the
defaults and with the mouth switches on the demo clip.
- Models are pinned by revision and checked by sha256 ([MODELS.md](MODELS.md)).
- What changed: [the changelog](https://lsdub.sndbnch.app/changelog). Something broke: the
[issue forms](https://github.com/HumanjavaEnterprises/comfyui-lsdub/issues/new/choose).

In honesty: 0.2.0, 0.2.1 and 0.2.2 landed in one day, before the install-path test existed. Two of them fixed breakage a
clean install would have caught (the phone recogniser in a fresh ComfyUI, and the Dub with the mouth switches on). The test
now runs on every pull request, before every publish, and weekly.

## Troubleshooting

- **The first Align run sits there.** It is downloading Whisper large-v3 (about 3 GB) with no progress bar in the UI.
Let it finish once.
- **The demo download fails.** Get `lsdub-demo-0.1.0.zip` from the GitHub Releases page by hand and run
`python scripts/fetch_demo.py --zip lsdub-demo-0.1.0.zip`.
- **The demo download fails.** Get `lsdub-demo-0.1.1.zip` from the GitHub Releases page by hand and run
`python scripts/fetch_demo.py --zip lsdub-demo-0.1.1.zip`.
- **Align warns about the lyrics.** If what is sung matches the lyrics poorly (below 0.5), it warns and places the
lyrics on the voice. Below 0.2 it stops and asks you to check the lyrics: they probably belong to another song.
- **A shot failed to dub.** It is reported, and by default the cut keeps its original frames. Run workflow 3 on the
Expand Down
2 changes: 1 addition & 1 deletion example_workflows/4-LSDub-Make-Your-Character-Sing.json
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@
true,
true,
"",
"sphinx"
"classic"
],
"color": "#523",
"title": "LSDub Align"
Expand Down
4 changes: 2 additions & 2 deletions lsdub_engine/VERSION
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pack_version: 0.2.2
uncommitted: 0
tree_sha256: 13cb87b83854a0f23de5f00ff3184811a78e3f004cd7fa6f5b01cb714066cb46
tests_sha256: 70cb132afd1ac5ac9aef39a95d11e23041668f2776c9d64f187b0a7fb48be82f
tree_sha256: 8041cc402dd6362c29c14cba0ebcaa6aaa81b8a8ee8e497cfd12cfedc76c5360
tests_sha256: acc5adad9b64dc605b06b8fc75ed5b9cda9fe516c72ac3b13c30e67a1384d395
Loading
Loading