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
21 changes: 21 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 All @@ -18,3 +22,20 @@ jobs:
with:
personal_access_token: ${{ secrets.REGISTRY_ACCESS_TOKEN }} # set this secret in the repo settings
skip_checkout: 'true'
site: # after a good publish: ask the microsite to deploy its main branch (it serves /changelog)
needs: publish
runs-on: ubuntu-latest
steps:
- name: Dispatch lsdub-release to the microsite
env:
TOKEN: ${{ secrets.MICROSITE_DISPATCH_TOKEN }}
TAG: ${{ github.ref_name }}
run: |
if [ -z "$TOKEN" ]; then
echo "::notice title=Site deploy skipped::MICROSITE_DISPATCH_TOKEN is not set, so the microsite was not asked to deploy. Add it (CONTRIBUTING.md, Releases) or deploy the site by hand."
exit 0
fi
curl -sSf -X POST -H "Authorization: Bearer $TOKEN" -H "Accept: application/vnd.github+json" \
https://api.github.com/repos/HumanjavaEnterprises/lsdub.web.microsite.src/dispatches \
-d "{\"event_type\":\"lsdub-release\",\"client_payload\":{\"tag\":\"$TAG\"}}"
echo "::notice title=Site deploy requested::lsdub-release $TAG sent to the microsite"
40 changes: 40 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,43 @@ 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 and checks the site
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:
- `REGISTRY_ACCESS_TOKEN` (here): the Comfy Registry publisher key, already set.
- `MICROSITE_DISPATCH_TOKEN` (here): a fine-grained GitHub token, resource owner HumanjavaEnterprises, repository access only
`lsdub.web.microsite.src`, permission Contents: Read and write (what `POST /repos/.../dispatches` needs). Without it the
publish job's site step prints a notice and skips, and `release.py` starts the deploy itself with your `gh` login.
- `CLOUDFLARE_API_TOKEN` (in the microsite repo): see its README, Deploys.
20 changes: 18 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,12 +202,28 @@ 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.
- 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
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: f36b7410d7dc3461fba57844603c81a5ba5ec37adb160148f9dc50595e4f19ba
tests_sha256: 59f5e441dbefa42caf1faf35824ac93cfec99b3e58b280a0e522d2f0f8759edb
2 changes: 1 addition & 1 deletion lsdub_engine/audits/qa.py
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,7 @@ def asked_travel(s):


EV_KEYS = ("onset_hit", "onset_n", "closure_hit", "closure_n", "spurious", "spurious_take", "open_ratio", "open_n")
LAG_WINDOW_S = 0.2 # a mouth rise this near a sung onset, either side, is that onset's rise (G10 lane 04's per-onset reading)
LAG_WINDOW_S = 0.2 # a mouth rise this near a sung onset, either side, is that onset's rise (the per-onset reading)


def vocal_events(vocal, align=None, phone_models=None):
Expand Down
6 changes: 3 additions & 3 deletions scripts/fetch_demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@
import urllib.request
import zipfile

VERSION = '0.1.0'
TAG = f'v{VERSION}'
VERSION = '0.1.1'
TAG = 'demo-0.1.1'
URL = f'https://github.com/HumanjavaEnterprises/comfyui-lsdub/releases/download/{TAG}/lsdub-demo-{VERSION}.zip'
SHA256 = 'a431085d931f2b983b620d31710ac868a459d461a6dcb158177d199637790edb'
SHA256 = '0b15dfcf069b6dc2cac25bbe312137eda435e4ac350cce6b61436419fd2b518c'


def unpack(zf, dst):
Expand Down
Loading
Loading