Skip to content

fix: transcribe — cut audio-only chunks, so a video doesn't re-encode to VP9 - #12

Open
1Croydan1 wants to merge 1 commit into
mainfrom
fix/transcribe-video-vn
Open

fix: transcribe — cut audio-only chunks, so a video doesn't re-encode to VP9#12
1Croydan1 wants to merge 1 commit into
mainfrom
fix/transcribe-video-vn

Conversation

@1Croydan1

Copy link
Copy Markdown
Collaborator

Симптом

Иван скинул Альберту видео на 2 минуты — бот «завис». В контейнере:

ffmpeg -ss 0 -t 126.233 -i inbox/…IMG_0932.MOV -ac 1 -c:a libopus -b:a 24k chunk_000.webm
   101% CPU, 3:55 машинного времени и не закончил

Причина

Чанк пишется в .webm, и без -vn ffmpeg мапит ещё и видеодорожку — перекодируя её в VP9. «Аудио-чанк» для 127 секунд успел распухнуть до 6.6 МБ (Opus 24 кбит/с дал бы ~380 КБ), прежде чем его прибили. Эти пиксели потом ещё и грузятся в эндпоинт диктовки, который на них не смотрит.

Аудиофайлы баг полностью скрывали: у них нет видеопотока, который можно смапить. Поэтому скилл выглядел исправным — до тех пор, пока видео не начало доходить до чата (octo#9).

Починка

-vn в команду нарезки. То же самое настоящее видео (2:07) теперь расшифровывается за 16 секунд end-to-end (8.2x реального времени) вместо таймаута:

[in]  inbox/…IMG_0932.MOV  00:02:06
[cut] 7 pauses found → 1 chunks (median 126s)
[api] 1/1 chunks
[out] out/…_transcript.txt  1885 chars  in 15s = 8.2x real time

Заодно добавлен guard if __name__ == "__main__": файл заканчивался голым вызовом main(), поэтому импорт модуля запускал CLI и argparse убивал процесс — ровно поэтому у скилла и не было тестов. Запуск скриптом не меняется.

Тесты

5, прогнаны, и проверено что они падают без фикса — чанк, нарезанный из видео, приходил как ['video', 'audio'] вместо ['audio']:

- ['video', 'audio']
+ ['audio'] : a chunk must be audio-only — a video stream means -vn was lost
FAILED (failures=1)

Проверяют инвариант напрямую: в чанке нет видеопотока, размер — как у речи, а не как у пикселей, режется быстро, аудио-вход продолжает работать, и вырезается именно запрошенный диапазон. Сети и токенов не трогают — только ffmpeg-сторона.

Зелёные локально (ffmpeg 8.1.1) и на боевом видео в задеплоенном образе (ffmpeg 6.1.1).

🤖 Generated with Claude Code

… to VP9

Sending a 2-minute video to Albert pinned a core at 100% for four minutes and
never produced a transcript. The chunker writes `.webm`, and without `-vn`
ffmpeg also maps the input's video stream and re-encodes it to VP9: the "audio
chunk" for a 127-second clip had grown to 6.6 MB (24 kbps Opus would be ~380 KB)
before the run was killed. Those pixels are then uploaded and ignored — the
dictation endpoint only listens.

Audio-only inputs hid this completely: they have no video stream to map, which
is why the skill looked fine until videos could actually reach the chat.

With `-vn`, the same real 2:07 video transcribes in 16 s end to end (8.2x real
time) instead of timing out.

Also adds the `if __name__ == "__main__"` guard: the module ended in a bare
`main()` call, so importing it ran the CLI and argparse killed the process —
the reason it had no tests. Running it as a script is unchanged.

Tests: 5, all run, and verified to fail without the fix (a chunk cut from a
video came back as ['video', 'audio'] instead of ['audio']). They assert the
invariant directly — chunks carry no video stream, stay the size of speech
rather than of pixels, finish quickly, keep working for audio-only inputs, and
still cut the range asked for.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant