@gentbajko/slopify 2.5.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -21
- package/NOTICE +12 -0
- package/README.md +21 -40
- package/SUBTITLES.md +1 -1
- package/dist/adapter-registry.js +3 -0
- package/dist/adapters/alignment/cache.js +4 -1
- package/dist/adapters/alignment/ctc.js +25 -23
- package/dist/adapters/alignment/index.js +37 -6
- package/dist/adapters/alignment/multilingual.js +267 -0
- package/dist/adapters/alignment/protocol.js +11 -0
- package/dist/adapters/alignment/quality.js +4 -3
- package/dist/adapters/alignment/sentences.js +95 -0
- package/dist/adapters/alignment/spec.js +24 -0
- package/dist/adapters/alignment/spell.js +769 -0
- package/dist/adapters/alignment/text.js +56 -9
- package/dist/adapters/alignment/window.js +34 -30
- package/dist/adapters/alignment/worker.js +23 -21
- package/dist/adapters/explain.js +11 -11
- package/dist/adapters/host-cli/index.js +44 -5
- package/dist/adapters/host-cli/transport.js +7 -5
- package/dist/adapters/image/bytes.js +2 -2
- package/dist/adapters/image/codex-output.js +1 -1
- package/dist/adapters/image/codex.js +87 -22
- package/dist/adapters/image/fal.js +13 -5
- package/dist/adapters/image/google.js +11 -8
- package/dist/adapters/image/openai.js +14 -7
- package/dist/adapters/image/reference.js +34 -0
- package/dist/adapters/image/replicate.js +7 -2
- package/dist/adapters/image/video.js +2 -2
- package/dist/adapters/key-probes.js +36 -0
- package/dist/adapters/llm/claude-code.js +168 -32
- package/dist/adapters/llm/cli-login-error.js +1 -1
- package/dist/adapters/llm/codex-limits.js +157 -0
- package/dist/adapters/llm/codex.js +99 -12
- package/dist/adapters/llm/document-workspace.js +2 -2
- package/dist/adapters/llm/gemini-workspace.js +1 -1
- package/dist/adapters/llm/gemini.js +16 -3
- package/dist/adapters/llm/image-workspace.js +58 -0
- package/dist/adapters/llm/openrouter.js +11 -3
- package/dist/adapters/llm/run-cli.js +12 -7
- package/dist/adapters/tts/cartesia.js +10 -0
- package/dist/adapters/tts/elevenlabs.js +31 -9
- package/dist/adapters/tts/inworld-async.js +9 -5
- package/dist/adapters/tts/inworld.js +17 -3
- package/dist/adapters/tts/openai.js +3 -0
- package/dist/adapters/tts/voice-languages.js +80 -0
- package/dist/assets/fonts/noto/NotoSans-Regular.ttf +0 -0
- package/dist/assets/fonts/noto/NotoSansArabic-Regular.ttf +0 -0
- package/dist/assets/fonts/noto/NotoSansDevanagari-Regular.ttf +0 -0
- package/dist/assets/fonts/noto/NotoSansHebrew-Regular.ttf +0 -0
- package/dist/assets/fonts/noto/NotoSansThai-Regular.ttf +0 -0
- package/dist/assets/fonts/noto/OFL.txt +93 -0
- package/dist/assets/fonts/noto/SOURCE.txt +18 -0
- package/dist/assets/sample/sample-audiobook.tar +0 -0
- package/dist/assets/sample/sample-podcast.tar +0 -0
- package/dist/assets/sample/sample-project.tar +0 -0
- package/dist/catalog/merge.js +132 -0
- package/dist/catalog/registry.js +13 -13
- package/dist/catalog/schema.js +2 -0
- package/dist/catalog/store.js +147 -8
- package/dist/compose.yaml +71 -0
- package/dist/edge/autostart/docker-record.js +32 -0
- package/dist/edge/autostart/docker.js +50 -0
- package/dist/edge/autostart/index.js +78 -0
- package/dist/edge/autostart/launcher.js +176 -0
- package/dist/edge/autostart/model.js +3 -0
- package/dist/edge/autostart/native.js +210 -0
- package/dist/edge/autostart/prompt.js +66 -0
- package/dist/edge/autostart/service.js +81 -0
- package/dist/edge/cli.js +57 -51
- package/dist/edge/docker-install/activation.js +56 -0
- package/dist/edge/docker-install/apply.js +458 -0
- package/dist/edge/docker-install/engine.js +362 -0
- package/dist/edge/docker-install/run.js +154 -0
- package/dist/edge/docker-install/state.js +146 -0
- package/dist/edge/{docker-projects → docker-install}/volume.js +1 -5
- package/dist/edge/docker.js +14 -22
- package/dist/edge/host-cli.js +1 -1
- package/dist/edge/http/actions.js +32 -10
- package/dist/edge/http/app.js +58 -2
- package/dist/edge/http/auditions.js +70 -0
- package/dist/edge/http/autostart.js +37 -0
- package/dist/edge/http/channel-memory.js +92 -0
- package/dist/edge/http/channels.js +128 -0
- package/dist/edge/http/entries.js +22 -3
- package/dist/edge/http/files.js +1 -1
- package/dist/edge/http/folder-location.js +1 -1
- package/dist/edge/http/home.js +39 -0
- package/dist/edge/http/host-cli.js +29 -5
- package/dist/edge/http/narration-peaks.js +76 -0
- package/dist/edge/http/onboarding.js +152 -0
- package/dist/edge/http/open-folder.js +1 -1
- package/dist/edge/http/patch-notes.js +45 -0
- package/dist/edge/http/planning.js +4 -2
- package/dist/edge/http/project-create.js +87 -0
- package/dist/edge/http/projects.js +31 -99
- package/dist/edge/http/prompts.js +40 -3
- package/dist/edge/http/pronunciations.js +23 -4
- package/dist/edge/http/providers.js +86 -0
- package/dist/edge/http/reviews.js +121 -0
- package/dist/edge/http/revision-files.js +1 -1
- package/dist/edge/http/revisions.js +1 -1
- package/dist/edge/http/run-cost.js +25 -0
- package/dist/edge/http/schedules.js +111 -6
- package/dist/edge/http/settings.js +84 -6
- package/dist/edge/http/storage-files.js +50 -0
- package/dist/edge/http/storage.js +29 -2
- package/dist/edge/http/studio.js +207 -0
- package/dist/edge/http/style-preview.js +100 -0
- package/dist/edge/http/subtitles.js +1 -1
- package/dist/edge/http/trash.js +69 -0
- package/dist/edge/http/update.js +24 -3
- package/dist/edge/http/whats-new.js +15 -0
- package/dist/edge/http/youtube-edits.js +83 -0
- package/dist/edge/native-update.js +62 -0
- package/dist/host-cli/open-folder.js +10 -10
- package/dist/host-cli/runtime.js +9 -1
- package/dist/kernel/db/migrations/0025-automatic-reviews.sql +40 -0
- package/dist/kernel/db/migrations/0026-schedule-topic-generation.sql +23 -0
- package/dist/kernel/db/migrations/0027-run-cost.sql +58 -0
- package/dist/kernel/db/migrations/0030-automatic-retries.sql +18 -0
- package/dist/kernel/db/migrations/0031-prompt-history-and-description-edits.sql +33 -0
- package/dist/kernel/db/migrations/0032-channels.sql +65 -0
- package/dist/kernel/db/migrations/0034-script-prompts.sql +23 -0
- package/dist/kernel/db/migrations/0035-narration-aliases.sql +13 -0
- package/dist/kernel/db/migrations/0037-project-uploads.sql +8 -0
- package/dist/kernel/db/migrations/0038-voice-languages.sql +7 -0
- package/dist/kernel/db/migrations/0039-channel-essentials.sql +64 -0
- package/dist/kernel/db/migrations/0040-standalone-usage.sql +35 -0
- package/dist/kernel/paths.js +27 -6
- package/dist/kernel/pipeline.js +4 -1
- package/dist/kernel/ports/host-cli.js +122 -14
- package/dist/kernel/ports/key-probe.js +1 -0
- package/dist/kernel/ports/languages.js +157 -0
- package/dist/kernel/ports/model.js +5 -2
- package/dist/kernel/ports/narration-aliases.js +60 -0
- package/dist/kernel/ports/plan-limits.js +36 -0
- package/dist/kernel/runner/attempt.js +17 -8
- package/dist/kernel/runner/audition.js +36 -0
- package/dist/kernel/runner/graph.js +24 -5
- package/dist/kernel/runner/index.js +35 -5
- package/dist/kernel/runner/meter.js +1 -0
- package/dist/kernel/runner/providers.js +142 -7
- package/dist/kernel/runner/retry-policy.js +43 -0
- package/dist/kernel/runner/standalone.js +134 -0
- package/dist/kernel/runner/work-authority.js +28 -2
- package/dist/main.js +272 -16
- package/dist/patch-notes/0.4.2-to-1.0.md +93 -0
- package/dist/patch-notes/1.0-to-2.0.md +74 -0
- package/dist/patch-notes/2.0-to-3.0.md +257 -0
- package/dist/patch-notes/3.0.0.md +70 -0
- package/dist/patch-notes/index.json +26 -0
- package/dist/slices/admission/model.js +27 -0
- package/dist/slices/admission/repo.js +24 -4
- package/dist/slices/admission/rules.js +79 -1
- package/dist/slices/admission/schema.js +58 -1
- package/dist/slices/admission/short-mode.js +47 -0
- package/dist/slices/admission/start.js +41 -5
- package/dist/slices/article/continuation.js +2 -2
- package/dist/slices/article/provided-entries.js +2 -2
- package/dist/slices/article/run.js +6 -2
- package/dist/slices/article/segments.js +3 -3
- package/dist/slices/backups/folder.js +14 -6
- package/dist/slices/batch/index.js +7 -2
- package/dist/slices/cancel/index.js +1 -1
- package/dist/slices/channels/cast-images.js +110 -0
- package/dist/slices/channels/cast-match.js +32 -0
- package/dist/slices/channels/images.js +19 -0
- package/dist/slices/channels/model.js +5 -0
- package/dist/slices/channels/rebrand.js +100 -0
- package/dist/slices/channels/repo.js +218 -0
- package/dist/slices/channels/runs.js +129 -0
- package/dist/slices/channels/schema.js +129 -0
- package/dist/slices/channels/service.js +180 -0
- package/dist/slices/channels/studio-csv.js +110 -0
- package/dist/slices/channels/videos.js +120 -0
- package/dist/slices/checkpoints/recovery.js +10 -0
- package/dist/slices/control/index.js +2 -1
- package/dist/slices/document/fonts.js +1 -1
- package/dist/slices/document/render.js +1 -1
- package/dist/slices/episodes/related.js +90 -0
- package/dist/slices/episodes/repo.js +60 -0
- package/dist/slices/episodes/service.js +58 -0
- package/dist/slices/episodes/summarize.js +170 -0
- package/dist/slices/estimate/index.js +109 -28
- package/dist/slices/estimate/requests.js +60 -2
- package/dist/slices/fixes/rules.js +73 -0
- package/dist/slices/fonts/coverage.js +82 -0
- package/dist/slices/fonts/sfnt.js +74 -0
- package/dist/slices/images/run.js +8 -5
- package/dist/slices/images/scale.js +84 -0
- package/dist/slices/library/diff.js +122 -0
- package/dist/slices/library/history.js +100 -0
- package/dist/slices/library/model.js +3 -0
- package/dist/slices/library/photorealistic.js +49 -0
- package/dist/slices/library/repo.js +19 -14
- package/dist/slices/library/save.js +62 -12
- package/dist/slices/library/slots.js +7 -1
- package/dist/slices/library/used-by.js +153 -0
- package/dist/slices/loudness/level-pieces.js +41 -0
- package/dist/slices/loudness/loudnorm.js +164 -0
- package/dist/slices/loudness/model.js +153 -0
- package/dist/slices/model-upkeep/model.js +10 -0
- package/dist/slices/model-upkeep/switch.js +217 -0
- package/dist/slices/model-upkeep/usage.js +183 -0
- package/dist/slices/narration/aliases-library.js +31 -0
- package/dist/slices/narration/aliases-schema.js +53 -0
- package/dist/slices/narration/aliases.js +49 -0
- package/dist/slices/narration/blocks.js +352 -0
- package/dist/slices/narration/chunk.js +19 -7
- package/dist/slices/narration/concat.js +2 -2
- package/dist/slices/narration/describe.js +45 -0
- package/dist/slices/narration/pauses-model.js +63 -0
- package/dist/slices/narration/pauses.js +269 -0
- package/dist/slices/narration/peaks-model.js +1 -0
- package/dist/slices/narration/peaks.js +94 -0
- package/dist/slices/narration/preparation.js +21 -3
- package/dist/slices/narration/pronunciation-chunks.js +3 -3
- package/dist/slices/narration/pronunciation.js +72 -25
- package/dist/slices/narration/run.js +6 -6
- package/dist/slices/narration/shared-glossary.js +1 -1
- package/dist/slices/narration/steering.js +15 -4
- package/dist/slices/notifications/notifier.js +21 -3
- package/dist/slices/notifications/rules.js +22 -1
- package/dist/slices/onboarding/copy.js +143 -0
- package/dist/slices/onboarding/first-run.js +46 -0
- package/dist/slices/onboarding/install.js +119 -0
- package/dist/slices/onboarding/model.js +64 -0
- package/dist/slices/onboarding/packs.js +491 -0
- package/dist/slices/onboarding/quick-short.js +129 -0
- package/dist/slices/onboarding/sample.js +132 -0
- package/dist/slices/onboarding/state.js +68 -0
- package/dist/slices/onboarding/template.js +73 -0
- package/dist/slices/patch-notes/library.js +73 -0
- package/dist/slices/patch-notes/seen.js +77 -0
- package/dist/slices/play-drafts/convert.js +125 -6
- package/dist/slices/play-drafts/readiness.js +3 -0
- package/dist/slices/play-drafts/repo.js +2 -0
- package/dist/slices/play-drafts/review-inputs.js +20 -3
- package/dist/slices/play-drafts/schema.js +89 -0
- package/dist/slices/play-drafts/service.js +4 -1
- package/dist/slices/play-drafts/start.js +43 -18
- package/dist/slices/project-templates/from-project.js +50 -4
- package/dist/slices/project-templates/one-off.js +26 -0
- package/dist/slices/project-templates/repo.js +2 -1
- package/dist/slices/project-templates/service.js +15 -4
- package/dist/slices/project-templates/setup.js +18 -2
- package/dist/slices/rebuild/admission-repo.js +1 -1
- package/dist/slices/rebuild/model.js +6 -0
- package/dist/slices/rebuild/preview-details.js +46 -3
- package/dist/slices/rebuild/preview-plan.js +13 -6
- package/dist/slices/rebuild/recipe-audio-parts.js +40 -7
- package/dist/slices/rebuild/recipe-audio.js +66 -12
- package/dist/slices/rebuild/recipe-build.js +8 -4
- package/dist/slices/rebuild/recipe-cast.js +18 -0
- package/dist/slices/rebuild/recipe-checkpoints.js +11 -9
- package/dist/slices/rebuild/recipe-describe.js +93 -0
- package/dist/slices/rebuild/recipe-edit.js +13 -1
- package/dist/slices/rebuild/recipe-exports.js +62 -8
- package/dist/slices/rebuild/recipe-input-schema.js +35 -0
- package/dist/slices/rebuild/recipe-legacy.js +9 -0
- package/dist/slices/rebuild/recipe-loudness.js +45 -0
- package/dist/slices/rebuild/recipe-model.js +25 -6
- package/dist/slices/rebuild/recipe-pauses.js +7 -0
- package/dist/slices/rebuild/recipe-preparation.js +3 -3
- package/dist/slices/rebuild/recipe-provider-choice.js +11 -1
- package/dist/slices/rebuild/recipe-reference.js +15 -1
- package/dist/slices/rebuild/recipe-reviews.js +117 -0
- package/dist/slices/rebuild/recipe-save.js +4 -1
- package/dist/slices/rebuild/recipe-shorts.js +23 -3
- package/dist/slices/rebuild/recipe-text.js +114 -19
- package/dist/slices/rebuild/recipe-validation.js +14 -2
- package/dist/slices/rebuild/recipe-visual.js +96 -33
- package/dist/slices/rebuild/recipe-voices.js +286 -0
- package/dist/slices/rebuild/recipe-work.js +77 -6
- package/dist/slices/rebuild/recipe-youtube.js +2 -0
- package/dist/slices/rebuild/recovery-conflict.js +7 -3
- package/dist/slices/rebuild/recovery-model.js +3 -0
- package/dist/slices/rebuild/recovery-selection.js +28 -2
- package/dist/slices/rebuild/recovery.js +35 -17
- package/dist/slices/rebuild/repo.js +3 -3
- package/dist/slices/rebuild/retry.js +18 -0
- package/dist/slices/rebuild/review-redo.js +110 -0
- package/dist/slices/rebuild/runtime-actions.js +5 -0
- package/dist/slices/rebuild/runtime-admission.js +4 -1
- package/dist/slices/rebuild/runtime-animate.js +4 -4
- package/dist/slices/rebuild/runtime-article.js +5 -5
- package/dist/slices/rebuild/runtime-document.js +4 -4
- package/dist/slices/rebuild/runtime-export-bed.js +43 -0
- package/dist/slices/rebuild/runtime-export-edit.js +70 -11
- package/dist/slices/rebuild/runtime-export-inputs.js +52 -10
- package/dist/slices/rebuild/runtime-export-short.js +85 -0
- package/dist/slices/rebuild/runtime-export.js +84 -19
- package/dist/slices/rebuild/runtime-figure-card.js +87 -0
- package/dist/slices/rebuild/runtime-image.js +21 -2
- package/dist/slices/rebuild/runtime-local.js +148 -24
- package/dist/slices/rebuild/runtime-materialize.js +8 -0
- package/dist/slices/rebuild/runtime-narration-reuse.js +2 -1
- package/dist/slices/rebuild/runtime-narration-text.js +7 -7
- package/dist/slices/rebuild/runtime-pictures.js +28 -0
- package/dist/slices/rebuild/runtime-piece-label.js +27 -0
- package/dist/slices/rebuild/runtime-provider.js +126 -18
- package/dist/slices/rebuild/runtime-publication.js +21 -5
- package/dist/slices/rebuild/runtime-review.js +237 -0
- package/dist/slices/rebuild/runtime-run.js +17 -11
- package/dist/slices/rebuild/runtime-shorts.js +44 -17
- package/dist/slices/rebuild/runtime-store.js +39 -10
- package/dist/slices/rebuild/runtime-subtitles.js +72 -19
- package/dist/slices/rebuild/runtime-voices.js +103 -0
- package/dist/slices/rebuild/runtime-youtube.js +7 -6
- package/dist/slices/rebuild/soften.js +49 -0
- package/dist/slices/rebuild/transition-repo.js +9 -2
- package/dist/slices/research/run.js +4 -4
- package/dist/slices/research/synthesis.js +2 -2
- package/dist/slices/reviews/model.js +105 -0
- package/dist/slices/reviews/outcome.js +22 -0
- package/dist/slices/reviews/repo.js +106 -0
- package/dist/slices/reviews/rules.js +63 -0
- package/dist/slices/reviews/verdict.js +71 -0
- package/dist/slices/reviews/view.js +30 -0
- package/dist/slices/revisions/adopt-content.js +5 -2
- package/dist/slices/revisions/adopt.js +3 -1
- package/dist/slices/revisions/downloads.js +7 -1
- package/dist/slices/revisions/image-plan.js +183 -0
- package/dist/slices/revisions/mutation-assets.js +10 -0
- package/dist/slices/revisions/mutation-cues.js +71 -0
- package/dist/slices/revisions/mutation-request.js +2 -1
- package/dist/slices/revisions/mutations.js +97 -3
- package/dist/slices/revisions/schema.js +11 -1
- package/dist/slices/run-cost/limits.js +128 -0
- package/dist/slices/run-cost/meter.js +47 -0
- package/dist/slices/run-cost/panel.js +234 -0
- package/dist/slices/run-cost/pricing.js +92 -0
- package/dist/slices/run-cost/week.js +108 -0
- package/dist/slices/schedules/agenda.js +158 -0
- package/dist/slices/schedules/repo.js +58 -18
- package/dist/slices/schedules/scheduler.js +67 -16
- package/dist/slices/schedules/schema.js +138 -1
- package/dist/slices/schedules/service.js +43 -4
- package/dist/slices/schedules/similar.js +90 -0
- package/dist/slices/schedules/topic-list.js +163 -0
- package/dist/slices/schedules/topics.js +422 -0
- package/dist/slices/settings/first-run.js +102 -0
- package/dist/slices/settings/health.js +190 -0
- package/dist/slices/settings/key-guides.js +128 -0
- package/dist/slices/settings/key-test.js +85 -0
- package/dist/slices/settings/model.js +6 -1
- package/dist/slices/settings/playback.js +15 -0
- package/dist/slices/settings/repo.js +17 -3
- package/dist/slices/settings/voices.js +64 -4
- package/dist/slices/settings/whats-new.js +64 -0
- package/dist/slices/shorts/captions.js +9 -0
- package/dist/slices/shorts/pick.js +3 -3
- package/dist/slices/shorts/prompts.js +1 -1
- package/dist/slices/shorts/render.js +54 -5
- package/dist/slices/storage/asset-name.js +3 -0
- package/dist/slices/storage/backup-export.js +48 -9
- package/dist/slices/storage/backup-format.js +38 -1
- package/dist/slices/storage/backup-import.js +191 -19
- package/dist/slices/storage/delete-project.js +7 -4
- package/dist/slices/storage/documents.js +79 -0
- package/dist/slices/storage/files-location.js +531 -0
- package/dist/slices/storage/layout.js +14 -4
- package/dist/slices/storage/model.js +11 -0
- package/dist/slices/storage/portable.js +92 -12
- package/dist/slices/storage/reconcile.js +14 -1
- package/dist/slices/storage/repo.js +4 -1
- package/dist/slices/storage/schema.js +11 -0
- package/dist/slices/storage/trim.js +146 -0
- package/dist/slices/studio/disclosure.js +74 -0
- package/dist/slices/studio/model.js +28 -0
- package/dist/slices/studio/pack.js +209 -0
- package/dist/slices/studio/settings.js +133 -0
- package/dist/slices/style-preview/images.js +61 -0
- package/dist/slices/style-preview/render.js +161 -0
- package/dist/slices/style-preview/schema.js +45 -0
- package/dist/slices/style-preview/service.js +93 -0
- package/dist/slices/style-preview/settings.js +89 -0
- package/dist/slices/subtitles/captions.js +42 -9
- package/dist/slices/subtitles/model.js +22 -0
- package/dist/slices/subtitles/prepare.js +27 -16
- package/dist/slices/subtitles/transcript.js +1 -1
- package/dist/slices/thumbnail/run.js +7 -7
- package/dist/slices/trash/model.js +25 -0
- package/dist/slices/trash/service.js +273 -0
- package/dist/slices/uploads/repo.js +20 -0
- package/dist/slices/video/ambient-bed-schema.js +15 -0
- package/dist/slices/video/ambient-bed.js +95 -0
- package/dist/slices/video/ambient-mix.js +72 -0
- package/dist/slices/video/audio-inputs.js +2 -2
- package/dist/slices/video/cards.js +5 -2
- package/dist/slices/video/edit-list.js +23 -2
- package/dist/slices/video/edit-settings.js +13 -3
- package/dist/slices/video/ffmpeg.js +63 -9
- package/dist/slices/video/figure-card.js +492 -0
- package/dist/slices/video/figure-spans.js +51 -0
- package/dist/slices/video/plan.js +125 -13
- package/dist/slices/video/run.js +14 -12
- package/dist/slices/video/slideshow.js +39 -4
- package/dist/slices/voices/attribution.js +69 -0
- package/dist/slices/voices/audio-files.js +82 -0
- package/dist/slices/voices/audition.js +25 -0
- package/dist/slices/voices/cast.js +56 -0
- package/dist/slices/voices/grouping.js +49 -0
- package/dist/slices/voices/join.js +35 -0
- package/dist/slices/voices/languages.js +25 -0
- package/dist/slices/voices/model.js +179 -0
- package/dist/slices/voices/palette.js +26 -0
- package/dist/slices/voices/panel.js +91 -0
- package/dist/slices/voices/portraits.js +55 -0
- package/dist/slices/voices/script.js +136 -0
- package/dist/slices/voices/timing.js +58 -0
- package/dist/slices/youtube/answer.js +1 -1
- package/dist/slices/youtube/chapters.js +126 -0
- package/dist/slices/youtube/edits-repo.js +69 -0
- package/dist/slices/youtube/edits.js +89 -0
- package/dist/slices/youtube/placeholders.js +98 -0
- package/dist/slices/youtube/transcript.js +11 -4
- package/dist/updater/service.js +66 -21
- package/dist/web/assets/index-CUA2sUxU.css +1 -0
- package/dist/web/assets/index-CX590kE-.js +303 -0
- package/dist/web/assets/jetbrains-mono-cyrillic-400-normal-BEIGL1Tu.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-cyrillic-400-normal-ugxPyKxw.woff +0 -0
- package/dist/web/assets/jetbrains-mono-greek-400-normal-B9oWc5Lo.woff +0 -0
- package/dist/web/assets/jetbrains-mono-greek-400-normal-C190GLew.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff +0 -0
- package/dist/web/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-latin-ext-400-normal-Bc8Ftmh3.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-latin-ext-400-normal-fXTG6kC5.woff +0 -0
- package/dist/web/assets/jetbrains-mono-vietnamese-400-normal-CqNFfHCs.woff +0 -0
- package/dist/web/assets/{pdf-BLF2i8c2.js → pdf-BG8n_uc5.js} +1 -1
- package/dist/web/index.html +2 -2
- package/package.json +4 -4
- package/dist/edge/docker-launch.js +0 -81
- package/dist/edge/docker-projects/activation.js +0 -35
- package/dist/edge/docker-projects/claims.js +0 -85
- package/dist/edge/docker-projects/committed.js +0 -40
- package/dist/edge/docker-projects/engine.js +0 -461
- package/dist/edge/docker-projects/install.js +0 -254
- package/dist/edge/docker-projects/prune.js +0 -66
- package/dist/edge/docker-projects/recover.js +0 -100
- package/dist/edge/docker-projects/state.js +0 -225
- package/dist/web/assets/index-CktpxlJd.js +0 -171
- package/dist/web/assets/index-DB-vOnGU.css +0 -1
- package/scripts/docker-run.sh +0 -3
- /package/dist/edge/{docker-projects → docker-install}/tree.js +0 -0
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import { languageInfo } from "../../kernel/ports/languages.js";
|
|
2
|
+
import { englishSpec } from "./spec.js";
|
|
3
|
+
import { spellers, spokenNumber } from "./spell.js";
|
|
4
|
+
import { respoken, speechWords } from "./text.js";
|
|
5
|
+
// voidful/wav2vec2-xlsr-multilingual-56 (Apache-2.0) as converted to ONNX by NewComer00,
|
|
6
|
+
// pinned to one revision. The q4 file: 4-bit weights, about a quarter of the fp32 size.
|
|
7
|
+
const revision = "2d48b01b6429d9018f81914550565112d56f6ba7";
|
|
8
|
+
export const multilingualModel = {
|
|
9
|
+
filename: "wav2vec2-xlsr-multilingual-56-q4-fcf93903.onnx",
|
|
10
|
+
url: `https://huggingface.co/NewComer00/wav2vec2-xlsr-multilingual-56-ONNX/resolve/${revision}/onnx/model_q4.onnx`,
|
|
11
|
+
bytes: 247_576_761,
|
|
12
|
+
sha256: "fcf939032d4091cf232d6a2e751e172d0409e0c926db6283526151cf50ceb577",
|
|
13
|
+
timeoutMs: 1_200_000,
|
|
14
|
+
};
|
|
15
|
+
// The model's own labels (its vocab.json at the same revision): 9,913 of them, the blank is
|
|
16
|
+
// [PAD] and the word delimiter is "|".
|
|
17
|
+
const modelLabels = 9913;
|
|
18
|
+
const modelBlank = 9910;
|
|
19
|
+
const modelDelimiter = 9908;
|
|
20
|
+
// Each letter's lower- and upper-case label. The model was trained on Common Voice text in
|
|
21
|
+
// both cases, so a letter's probability is the sum of both.
|
|
22
|
+
const modelIds = {
|
|
23
|
+
a: [36, 10],
|
|
24
|
+
b: [37, 11],
|
|
25
|
+
c: [38, 12],
|
|
26
|
+
d: [39, 13],
|
|
27
|
+
e: [40, 14],
|
|
28
|
+
f: [41, 15],
|
|
29
|
+
g: [42, 16],
|
|
30
|
+
h: [43, 17],
|
|
31
|
+
i: [44, 18],
|
|
32
|
+
j: [45, 19],
|
|
33
|
+
k: [46, 20],
|
|
34
|
+
l: [47, 21],
|
|
35
|
+
m: [48, 22],
|
|
36
|
+
n: [49, 23],
|
|
37
|
+
o: [50, 24],
|
|
38
|
+
p: [51, 25],
|
|
39
|
+
q: [52, 26],
|
|
40
|
+
r: [53, 27],
|
|
41
|
+
s: [54, 28],
|
|
42
|
+
t: [55, 29],
|
|
43
|
+
u: [56, 30],
|
|
44
|
+
v: [57, 31],
|
|
45
|
+
w: [58, 32],
|
|
46
|
+
x: [59, 33],
|
|
47
|
+
y: [60, 34],
|
|
48
|
+
z: [61, 35],
|
|
49
|
+
ß: [145],
|
|
50
|
+
à: [146, 116],
|
|
51
|
+
á: [147, 117],
|
|
52
|
+
â: [148, 118],
|
|
53
|
+
ã: [149, 119],
|
|
54
|
+
ä: [150, 120],
|
|
55
|
+
æ: [152, 122],
|
|
56
|
+
ç: [153, 123],
|
|
57
|
+
è: [154, 124],
|
|
58
|
+
é: [155, 125],
|
|
59
|
+
ê: [156, 126],
|
|
60
|
+
ë: [157, 127],
|
|
61
|
+
ì: [158, 128],
|
|
62
|
+
í: [159, 129],
|
|
63
|
+
î: [160, 130],
|
|
64
|
+
ï: [161, 131],
|
|
65
|
+
ñ: [163, 133],
|
|
66
|
+
ò: [164, 134],
|
|
67
|
+
ó: [165, 135],
|
|
68
|
+
ô: [166, 136],
|
|
69
|
+
õ: [167, 137],
|
|
70
|
+
ö: [168, 138],
|
|
71
|
+
ù: [171, 141],
|
|
72
|
+
ú: [172, 142],
|
|
73
|
+
û: [173, 143],
|
|
74
|
+
ü: [174, 144],
|
|
75
|
+
ý: [175],
|
|
76
|
+
ÿ: [177, 253],
|
|
77
|
+
ą: [182, 181],
|
|
78
|
+
ć: [184, 183],
|
|
79
|
+
č: [188, 187],
|
|
80
|
+
ď: [189],
|
|
81
|
+
ę: [196, 195],
|
|
82
|
+
ě: [198, 197],
|
|
83
|
+
ł: [218, 217],
|
|
84
|
+
ń: [220, 219],
|
|
85
|
+
ň: [222],
|
|
86
|
+
œ: [230, 229],
|
|
87
|
+
ř: [233, 232],
|
|
88
|
+
ś: [235, 234],
|
|
89
|
+
š: [240, 239],
|
|
90
|
+
ť: [242],
|
|
91
|
+
ů: [247],
|
|
92
|
+
ź: [255, 254],
|
|
93
|
+
ż: [257, 256],
|
|
94
|
+
ž: [259, 258],
|
|
95
|
+
};
|
|
96
|
+
// The letters each language is written with beyond a–z. A letter outside its language is read
|
|
97
|
+
// without its accent ("Dvořák" in Spanish is "dvorak"), which is how a reader of that language
|
|
98
|
+
// would say it closely enough for timing.
|
|
99
|
+
export const alphabets = {
|
|
100
|
+
es: "áéíóúüñ",
|
|
101
|
+
de: "äöüß",
|
|
102
|
+
fr: "àâæçèéêëîïôœùûüÿ",
|
|
103
|
+
it: "àèéìíîòóùú",
|
|
104
|
+
pt: "áâãàçéêíóôõú",
|
|
105
|
+
ca: "àèéíïòóúüç",
|
|
106
|
+
nl: "áéëïóöüè",
|
|
107
|
+
pl: "ąćęłńóśźż",
|
|
108
|
+
cs: "áčďéěíňóřšťúůýž",
|
|
109
|
+
};
|
|
110
|
+
// The English values. Measured on 2026-09-27 with scripts/validate-multilingual-alignment.mjs
|
|
111
|
+
// on LibriVox narration (Spanish 64 s / 193 words, German 48 s / 102 words; English 57 s /
|
|
112
|
+
// 147 words on its own model as the baseline): folded to one language's letters, the q4
|
|
113
|
+
// model's word posteriors averaged 0.95-0.97, as the English model's do (0.96), no word fell
|
|
114
|
+
// below 0.2, and the audio of another language was refused at its first window. So the same
|
|
115
|
+
// gates hold, and loosening them would only let wrong audio through.
|
|
116
|
+
export const multilingualGates = {
|
|
117
|
+
meanPosterior: 0.48,
|
|
118
|
+
poorScore: 0.2,
|
|
119
|
+
poorShare: 0.3,
|
|
120
|
+
maximumError: 0.42,
|
|
121
|
+
anchorLetters: 20,
|
|
122
|
+
anchorConfidence: 0.75,
|
|
123
|
+
};
|
|
124
|
+
export function multilingualLanguages() {
|
|
125
|
+
return Object.keys(alphabets);
|
|
126
|
+
}
|
|
127
|
+
// The model and language view the aligner uses for a project language. English keeps its own
|
|
128
|
+
// model and every constant it had.
|
|
129
|
+
export function alignmentSpecFor(language) {
|
|
130
|
+
return language === undefined || language === "en" ? englishSpec : multilingualSpec(language);
|
|
131
|
+
}
|
|
132
|
+
// One language's view of the model: its labels are blank, the delimiter and that language's
|
|
133
|
+
// letters, and every other label (other alphabets, digits, punctuation, CJK) is left out, the
|
|
134
|
+
// way voidful's own decoder masks the vocabulary by language.
|
|
135
|
+
export function multilingualSpec(language) {
|
|
136
|
+
const alphabet = alphabets[language];
|
|
137
|
+
const speller = spellers[language];
|
|
138
|
+
if (alphabet === undefined || speller === undefined)
|
|
139
|
+
throw new Error(`Word timing does not support ${languageInfo(language).name}. Slopify times its captions sentence by sentence instead; this is a bug if you see it, so use Download diagnostics in Settings and report it.`);
|
|
140
|
+
const letters = [..."abcdefghijklmnopqrstuvwxyz", ...alphabet];
|
|
141
|
+
const ids = { "|": 1 };
|
|
142
|
+
for (const [index, letter] of letters.entries())
|
|
143
|
+
ids[letter] = index + 2;
|
|
144
|
+
const columns = [
|
|
145
|
+
[modelBlank],
|
|
146
|
+
[modelDelimiter],
|
|
147
|
+
...letters.map((letter) => modelIds[letter] ?? []),
|
|
148
|
+
];
|
|
149
|
+
const keep = new RegExp(`[^a-z${alphabet}]`, "gu");
|
|
150
|
+
const name = languageInfo(language).name;
|
|
151
|
+
return {
|
|
152
|
+
labels: columns.length,
|
|
153
|
+
delimiter: 1,
|
|
154
|
+
ids,
|
|
155
|
+
letters: ["", " ", ...letters],
|
|
156
|
+
modelLabels,
|
|
157
|
+
compact: (logits, frames) => compactLogits(logits, frames, columns),
|
|
158
|
+
words: (text, observed, aliases) => multilingualWords(text, language, observed, aliases),
|
|
159
|
+
respoken: (word, observed) => respoken(word, observed, (raw) => wordForms(raw, language, alphabet, speller)),
|
|
160
|
+
lettersOnly: (text) => text.toLowerCase().replace(keep, ""),
|
|
161
|
+
comparable: (text) => text.toLowerCase().replace(keep, ""),
|
|
162
|
+
gates: multilingualGates,
|
|
163
|
+
mismatch: `The audio does not closely match the ${name} transcript. Check the article and audio, including any intro or outro, before generating subtitles.`,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
// Log-sum-exp of each column's labels, frame by frame: the logits of a smaller model whose
|
|
167
|
+
// softmax is the original one restricted to these labels.
|
|
168
|
+
export function compactLogits(logits, frames, columns) {
|
|
169
|
+
const width = logits.length / frames;
|
|
170
|
+
const result = new Float32Array(frames * columns.length);
|
|
171
|
+
for (let frame = 0; frame < frames; frame += 1) {
|
|
172
|
+
const offset = frame * width;
|
|
173
|
+
for (const [column, labels] of columns.entries()) {
|
|
174
|
+
let max = -Infinity;
|
|
175
|
+
for (const label of labels)
|
|
176
|
+
max = Math.max(max, logits[offset + label] ?? -Infinity);
|
|
177
|
+
if (max === -Infinity) {
|
|
178
|
+
result[frame * columns.length + column] = -Infinity;
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
let sum = 0;
|
|
182
|
+
for (const label of labels)
|
|
183
|
+
sum += Math.exp((logits[offset + label] ?? -Infinity) - max);
|
|
184
|
+
result[frame * columns.length + column] = sum === 0 ? -Infinity : max + Math.log(sum);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return result;
|
|
188
|
+
}
|
|
189
|
+
// Display words keep their spelling; only the acoustic match uses the normalised, lower-case
|
|
190
|
+
// form in the language's alphabet.
|
|
191
|
+
// Narration aliases apply as in English (`text.ts#speechWords`).
|
|
192
|
+
export function multilingualWords(text, language, observed = "", aliases = []) {
|
|
193
|
+
const speller = spellers[language];
|
|
194
|
+
const alphabet = alphabets[language];
|
|
195
|
+
if (speller === undefined || alphabet === undefined)
|
|
196
|
+
return [];
|
|
197
|
+
return speechWords(text, observed, aliases, (raw) => wordForms(raw, language, alphabet, speller), `Local subtitles need a ${languageInfo(language).name} transcript with spoken words. Check the article text, then Try again.`);
|
|
198
|
+
}
|
|
199
|
+
function wordForms(raw, language, alphabet, speller) {
|
|
200
|
+
const plain = raw
|
|
201
|
+
.normalize("NFC")
|
|
202
|
+
.toLowerCase()
|
|
203
|
+
.replace(/[‘’ʼ`´]/g, "'");
|
|
204
|
+
const core = plain.replace(/^[^\p{L}\p{N}$£€]+|[^\p{L}\p{N}%]+$/gu, "");
|
|
205
|
+
if (core === "")
|
|
206
|
+
return [];
|
|
207
|
+
const currency = core.startsWith("$")
|
|
208
|
+
? speller.dollar
|
|
209
|
+
: core.startsWith("£")
|
|
210
|
+
? speller.pound
|
|
211
|
+
: core.startsWith("€") || core.endsWith("€")
|
|
212
|
+
? speller.euro
|
|
213
|
+
: "";
|
|
214
|
+
const percent = core.endsWith("%") ? speller.percent : "";
|
|
215
|
+
const clean = core.replace(/^[$£€]/, "").replace(/[%€]$/, "");
|
|
216
|
+
let forms;
|
|
217
|
+
if (/^\d[\d., {2}]*$/.test(clean) && /\d$/.test(clean))
|
|
218
|
+
forms = spokenNumber(clean, speller);
|
|
219
|
+
else {
|
|
220
|
+
const expanded = clean
|
|
221
|
+
.replaceAll("&", ` ${speller.and} `)
|
|
222
|
+
.replace(/\d+/g, (digits) => ` ${spokenNumber(digits, speller)[0] ?? ""} `);
|
|
223
|
+
forms = [spell(expanded, alphabet, raw, language)];
|
|
224
|
+
}
|
|
225
|
+
return forms.map((form) => [form, currency, percent].filter(Boolean).join(" "));
|
|
226
|
+
}
|
|
227
|
+
// Keeps the language's own letters, reads other accented Latin letters without the accent,
|
|
228
|
+
// drops apostrophes and the Catalan middle dot inside a word, and treats everything else that
|
|
229
|
+
// is not a letter as a word break.
|
|
230
|
+
function spell(text, alphabet, raw, language) {
|
|
231
|
+
let result = "";
|
|
232
|
+
for (const character of text) {
|
|
233
|
+
if (/[a-z]/.test(character) || alphabet.includes(character)) {
|
|
234
|
+
result += character;
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
if (character === "'" || character === "·")
|
|
238
|
+
continue;
|
|
239
|
+
if (!/\p{L}/u.test(character)) {
|
|
240
|
+
result += " ";
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
const folded = fold(character);
|
|
244
|
+
if (folded === undefined)
|
|
245
|
+
throw new Error(`Word timing for ${languageInfo(language).name} reads Latin letters only, and "${raw}" has letters from another alphabet. Write that word in Latin letters in the article (open the project, Edit project → Article), then Try again.`);
|
|
246
|
+
result += folded;
|
|
247
|
+
}
|
|
248
|
+
return result.replace(/\s+/g, " ").trim();
|
|
249
|
+
}
|
|
250
|
+
const ligatures = {
|
|
251
|
+
æ: "ae",
|
|
252
|
+
œ: "oe",
|
|
253
|
+
ß: "ss",
|
|
254
|
+
ø: "o",
|
|
255
|
+
đ: "d",
|
|
256
|
+
ð: "d",
|
|
257
|
+
þ: "th",
|
|
258
|
+
ł: "l",
|
|
259
|
+
ı: "i",
|
|
260
|
+
};
|
|
261
|
+
function fold(character) {
|
|
262
|
+
const ligature = ligatures[character];
|
|
263
|
+
if (ligature !== undefined)
|
|
264
|
+
return ligature;
|
|
265
|
+
const base = character.normalize("NFKD").replace(/\p{M}/gu, "");
|
|
266
|
+
return /^[a-z]+$/.test(base) ? base : undefined;
|
|
267
|
+
}
|
|
@@ -3,6 +3,17 @@ export const workerInput = z.object({
|
|
|
3
3
|
modelPath: z.string(),
|
|
4
4
|
pcmPath: z.string(),
|
|
5
5
|
text: z.string(),
|
|
6
|
+
// The project language; absent is English and its model.
|
|
7
|
+
language: z.string().optional(),
|
|
8
|
+
// Narration aliases the audio was read with; see speechWords.
|
|
9
|
+
aliases: z
|
|
10
|
+
.array(z.object({
|
|
11
|
+
written: z.string(),
|
|
12
|
+
spoken: z.string(),
|
|
13
|
+
wholeWord: z.boolean(),
|
|
14
|
+
caseSensitive: z.boolean(),
|
|
15
|
+
}))
|
|
16
|
+
.optional(),
|
|
6
17
|
});
|
|
7
18
|
export const omissionSchema = z.object({
|
|
8
19
|
start: z.number().finite().nonnegative(),
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { englishSpec } from "./spec.js";
|
|
1
2
|
// Compare acoustic recognition with the already aligned transcript. This catches extra
|
|
2
3
|
// speech and missing phrases even when a few forced words individually score well.
|
|
3
|
-
export function agreesWithSpeech(expected, observed, maximumError = 0.42) {
|
|
4
|
-
const left = expected
|
|
5
|
-
const right = observed
|
|
4
|
+
export function agreesWithSpeech(expected, observed, maximumError = 0.42, comparable = englishSpec.comparable) {
|
|
5
|
+
const left = comparable(expected);
|
|
6
|
+
const right = comparable(observed);
|
|
6
7
|
if (left.length === 0 || right.length === 0)
|
|
7
8
|
return false;
|
|
8
9
|
let previous = Uint16Array.from({ length: right.length + 1 }, (_, index) => index);
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
const frameSeconds = 0.02;
|
|
2
|
+
const shortestPause = 0.2;
|
|
3
|
+
// Loudness per 20 ms frame, then a threshold between the quiet floor and the loud level.
|
|
4
|
+
export function speechShape(samples, sampleRate = 16000) {
|
|
5
|
+
const size = Math.round(sampleRate * frameSeconds);
|
|
6
|
+
const frames = Math.floor(samples.length / size);
|
|
7
|
+
const duration = samples.length / sampleRate;
|
|
8
|
+
if (frames === 0)
|
|
9
|
+
return { speechStart: 0, speechEnd: duration, pauses: [] };
|
|
10
|
+
const levels = new Float32Array(frames);
|
|
11
|
+
for (let frame = 0; frame < frames; frame += 1) {
|
|
12
|
+
let sum = 0;
|
|
13
|
+
for (let index = frame * size; index < (frame + 1) * size; index += 1)
|
|
14
|
+
sum += (samples[index] ?? 0) ** 2;
|
|
15
|
+
levels[frame] = Math.sqrt(sum / size);
|
|
16
|
+
}
|
|
17
|
+
const sorted = Float32Array.from(levels).sort();
|
|
18
|
+
const floor = sorted[Math.floor(frames * 0.1)] ?? 0;
|
|
19
|
+
const loud = sorted[Math.floor(frames * 0.9)] ?? 0;
|
|
20
|
+
if (loud <= floor)
|
|
21
|
+
return { speechStart: 0, speechEnd: duration, pauses: [] };
|
|
22
|
+
const threshold = floor + (loud - floor) * 0.15;
|
|
23
|
+
const quiet = Array.from(levels, (level) => level < threshold);
|
|
24
|
+
const first = quiet.indexOf(false);
|
|
25
|
+
const last = quiet.lastIndexOf(false);
|
|
26
|
+
if (first === -1)
|
|
27
|
+
return { speechStart: 0, speechEnd: duration, pauses: [] };
|
|
28
|
+
const pauses = [];
|
|
29
|
+
let runStart = -1;
|
|
30
|
+
for (let frame = first; frame <= last; frame += 1) {
|
|
31
|
+
if (quiet[frame] === true) {
|
|
32
|
+
if (runStart === -1)
|
|
33
|
+
runStart = frame;
|
|
34
|
+
}
|
|
35
|
+
else if (runStart !== -1) {
|
|
36
|
+
if ((frame - runStart) * frameSeconds >= shortestPause)
|
|
37
|
+
pauses.push({ start: runStart * frameSeconds, end: frame * frameSeconds });
|
|
38
|
+
runStart = -1;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return { speechStart: first * frameSeconds, speechEnd: (last + 1) * frameSeconds, pauses };
|
|
42
|
+
}
|
|
43
|
+
export function sentencesOf(text, language) {
|
|
44
|
+
const segmenter = new Intl.Segmenter(language, { granularity: "sentence" });
|
|
45
|
+
return Array.from(segmenter.segment(text), (part) => part.segment.trim()).filter((sentence) => sentence !== "");
|
|
46
|
+
}
|
|
47
|
+
// Letters and digits: what takes time to say. Punctuation and spaces do not.
|
|
48
|
+
const weight = (text) => Math.max(1, text.replace(/[^\p{L}\p{N}]/gu, "").length);
|
|
49
|
+
export function sentenceTiming(text, language, shape) {
|
|
50
|
+
const sentences = sentencesOf(text, language);
|
|
51
|
+
if (sentences.length === 0)
|
|
52
|
+
return [];
|
|
53
|
+
const span = Math.max(0.1, shape.speechEnd - shape.speechStart);
|
|
54
|
+
const weights = sentences.map(weight);
|
|
55
|
+
const total = weights.reduce((sum, value) => sum + value, 0);
|
|
56
|
+
// How far a boundary may move to reach a pause: most of an average sentence, since letters
|
|
57
|
+
// are a rough measure of speaking time.
|
|
58
|
+
const reach = (span / sentences.length) * 0.75;
|
|
59
|
+
const bounds = [shape.speechStart];
|
|
60
|
+
let covered = 0;
|
|
61
|
+
for (const value of weights.slice(0, -1)) {
|
|
62
|
+
covered += value;
|
|
63
|
+
const estimate = shape.speechStart + (span * covered) / total;
|
|
64
|
+
const previous = bounds.at(-1) ?? shape.speechStart;
|
|
65
|
+
let best = estimate;
|
|
66
|
+
let distance = reach;
|
|
67
|
+
for (const pause of shape.pauses) {
|
|
68
|
+
const middle = (pause.start + pause.end) / 2;
|
|
69
|
+
if (middle <= previous + 0.1)
|
|
70
|
+
continue;
|
|
71
|
+
if (Math.abs(middle - estimate) < distance) {
|
|
72
|
+
best = middle;
|
|
73
|
+
distance = Math.abs(middle - estimate);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
bounds.push(Math.min(shape.speechEnd - 0.05, Math.max(previous + 0.05, best)));
|
|
77
|
+
}
|
|
78
|
+
bounds.push(shape.speechEnd);
|
|
79
|
+
const words = [];
|
|
80
|
+
for (const [index, sentence] of sentences.entries()) {
|
|
81
|
+
const start = bounds[index] ?? 0;
|
|
82
|
+
const end = Math.max(start + 0.05, bounds[index + 1] ?? start);
|
|
83
|
+
const parts = sentence.split(/\s+/).filter((part) => part !== "");
|
|
84
|
+
const shares = parts.map(weight);
|
|
85
|
+
const sum = shares.reduce((total, value) => total + value, 0);
|
|
86
|
+
let at = start;
|
|
87
|
+
for (const [position, part] of parts.entries()) {
|
|
88
|
+
const next = position === parts.length - 1 ? end : at + ((end - start) * (shares[position] ?? 1)) / sum;
|
|
89
|
+
words.push({ text: part, start: round(at), end: round(next) });
|
|
90
|
+
at = next;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return words;
|
|
94
|
+
}
|
|
95
|
+
const round = (seconds) => Math.round(seconds * 1000) / 1000;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { respoken, speechWords } from "./text.js";
|
|
2
|
+
import { letters as englishLetters, vocabulary as englishVocabulary } from "./vocabulary.js";
|
|
3
|
+
export const englishMismatch = "The audio does not closely match the English transcript. Check the article and audio, including any intro or outro, before generating subtitles.";
|
|
4
|
+
export const englishGates = {
|
|
5
|
+
meanPosterior: 0.48,
|
|
6
|
+
poorScore: 0.2,
|
|
7
|
+
poorShare: 0.3,
|
|
8
|
+
maximumError: 0.42,
|
|
9
|
+
anchorLetters: 20,
|
|
10
|
+
anchorConfidence: 0.75,
|
|
11
|
+
};
|
|
12
|
+
export const englishSpec = {
|
|
13
|
+
labels: 32,
|
|
14
|
+
delimiter: 4,
|
|
15
|
+
ids: englishVocabulary,
|
|
16
|
+
letters: englishLetters,
|
|
17
|
+
modelLabels: 32,
|
|
18
|
+
words: speechWords,
|
|
19
|
+
respoken,
|
|
20
|
+
lettersOnly: (text) => text.replace(/[^A-Z]/g, ""),
|
|
21
|
+
comparable: (text) => text.toUpperCase().replace(/[^A-Z']/g, ""),
|
|
22
|
+
gates: englishGates,
|
|
23
|
+
mismatch: englishMismatch,
|
|
24
|
+
};
|