Skip to content

ASR and Video Analysis ru

Hermes Agent edited this page Oct 1, 2026 · 1 revision

ASR и анализ видео

English | 中文 | 日本語 | 한국어 | Español | Português | Русский

Прикрепите видео Bilibili / YouTube без субтитров — browsa скачает аудио прямо на странице, запустит облачный ASR и получит транскрипт [mm:ss] — или запустит 视听精读 (аудиовизуальное глубокое чтение): документ из рисунков и текста о речи + визуале. ASR-провайдер сегодня — Volcengine Ark.

Почему «скачать → загрузить файл», а не прямая передача URL

Прямая передача URL мертва для ОБЕИХ платформ: Bilibili подписывает CDN-URL на IP сессии пользователя (сервер Ark не может их скачать); YouTube добавляет PO-token + привязку сессии + куки (серверные fetch получают 403). Браузер — клиент, чей IP совпадает с подписью, — должен сам скачать байты и загрузить их в Files API. Это вывод о первопричине, а не один вариант из нескольких.

Конвейер (восемь шагов)

  1. ATTACH_PAGE возвращает {mode:'asr-pending'} (отложенный по хранению хэндофф).
  2. buildAsrPendingCtx диспетчеризует по платформе: Bilibili ре-инжектит свой контент-скрипт, чтобы прочитать стримы; YouTube вызывает MAIN-world __browsaFetchFreshYouTubeStreams (свежий запрос /player, чеканящий текущий PO token).
  3. Выбор стрима: чистое аудио с наименьшим битрейтом (оно всё равно перекодируется), но ОТВЕРГАТЬ стримы короче 90% истинной длительности (реальный инцидент с обрезанным стримом); предпочитать AAC-LC (decodeAudioData может отвергнуть HE-AAC).
  4. Инъекция заголовков через DNR (lib/sidepanel/media-headers.js): Bilibili нужен Referer; YouTube ТАКЖЕ нужен rewrite Origin + куки (googlevideo отдаёт 403 на fetch расширения без заголовков — проверено вживую).
  5. Перекодирование в 16kHz mono WAV: m4s у Bilibili — это MP4 fMP4 без видео; Ark классифицирует файлы ПО СОДЕРЖИМОМУ как «video» → Invalid video_url → статус failed. WAV — эмпирически доказанный формат. Декод через Web Audio + рукописный ресемплинг линейной интерполяцией (чистый, тестируемый в Node).
  6. Загрузка в Files API (≤512MB multipart): expire_at = 30 дней, смысловые имена файлов; browsaArkFileCache хранит file_ids (ключ = base|key-fingerprint|assetId), так что то же видео пропускает повторную загрузку в течение 30 дней (проверка живости перед переиспользованием).
  7. Опрос статуса файла → потоковая транскрипция через /responses (input_audio.file_id), промпт принуждает [mm:ss] на каждую строку.
  8. ATTACH_ASR_CONFIRM сохраняет транскрипт + штамп videoSrc (предусловие для капсул таймкодов / панели таймлайна).

Защиты от усечения — никогда не сохранять частичный транскрипт молча (четыре слоя, по инцидентам)

  1. Явный max_output_tokens: 65536 на /responses (дефолтный потолок вывода модели молча режет посреди аудио).
  2. Парсить SSE-сигналы incomplete / finish_reason:'length' → truncated:true.
  3. Гейт полноты: последний таймкод < 90% длительности видео → throw, fail open в простой текст + тост (НЕ сохраняется).
  4. Гейт дыр: largestTranscriptGapSec интервально мержит таймлайн; дыра > 300с — отказ (81-минутное видео однажды потеряло час посередине).

Глубокое чтение видео (само видео идёт модели)

input_video (+ опциональный отдельный input_audio), max_output_tokens 65536, потоковый вывод из рисунков и текста. Дисциплина промпта (откалибрована на реальных прогонах): помечать спикеров, как только появляется ЛЮБОЙ второй голос, дописывать различимые имена, сжимать рекламные вставки до одной строки, скриншоты ключевых кадров ТОЛЬКО когда аргумент зависит от их созерцания (мягкий хинт плотности + явный список «не снимать»; единственный жёсткий потолок — клиентский SAFETY_KEYFRAME_CAP 24 — защита от патологического вывода, а не ручка качества). Маркеры [图N] делят один протокол заякоривания с картинками страницы и панелью таймлайна.

Заметки по платформам

  • Bilibili: список дорожек /x/player/wbi/v2 + CDN-JSON субтитров запрашиваются активно — независимо от тумблера CC.
  • YouTube: timedtext отдаёт реальный контент ТОЛЬКО собственным POT-запросам плеера (прямые fetch captionTracks.baseUrl возвращают пустые тела); перехватчик ловит материал, только если CC был включён хотя бы раз. Fallback-этап 2c ведёт модуль субтитров плеера, чтобы отчеканить один авторизованный запрос (короткая вспышка субтитров на экране ожидаема); вердикт «треклист пуст» негативно кэшируется по videoId.
  • «Нет субтитров» оценивается по структурированному флагу noTranscript, а НЕ по текстовому маркеру ## 字幕 (молчаливый Jina-fallback авто-режима глотает текстовые маркеры — реальный баг).

Шов для второго ASR-провайдера (зарезервирован)

lib/asr-providers.js (реестр метаданных; ноль изменений UI) + ASR_ADAPTERS в attach-asr.js (одинаковая сигнатура {transcribeAudio, analyzeVideo}). Трудное место — всегда возможность эндпоинта загружать файлы (длинное аудио не может ехать инлайн base64). Полный адаптер Qwen/DashScope был построен и удалён через день (browser→OSS нестабилен; сохранён в git-истории); fallback tabCapture «запись во время воспроизведения» отвергнут (пауза/пропуск = тишина — невоспроизведённое видео не транскрибировать).


Авторитетные версии: ASR-and-Video-Analysis (англ.) / ASR-and-Video-Analysis-zh (кит.) — снимок первичного перевода ИИ, синхронизирован 2026-10-01.

Clone this wiki locally