Я принимаю поток RTMP и преобразовываю его в фрагментированный файл MP4 в JavaScript. Это заняло неделю работы, но я почти закончил эту задачу. Я создаю действительный атом ftyp
, атом moov
и атом moof
, и первый кадр видео фактически воспроизводится (со звуком), прежде чем он перейдет в бесконечную буферизацию без ошибок, перечисленных в chrome://media-internals
Подключив видео к ffprobe
, я получаю сообщение об ошибке, похожее на:
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x558559198080] Failed to add index entry
Last message repeated 368 times
[h264 @ 0x55855919b300] Invalid NAL unit size (-619501801 > 966).
[h264 @ 0x55855919b300] Error splitting the input into NAL units.
Это привело меня к масштабному поиску проблем с выравниванием данных или недопустимых смещений байтов в моих атомах tfhd
и trun
, однако независимо от того, где я искал или как я разрезал данные, я не мог найти никаких проблем в атоме moof
.
Затем я взял исходный файл FLV и преобразовал его в MP4 в формате ffmpeg
с помощью следующей команды:
ffmpeg -i ~/Videos/rtmp/big_buck_bunny.flv -c copy -ss 5 -t 10 -movflags frag_keyframe+empty_moov+faststart test.mp4
Я открыл как созданный мной MP4, так и вывод MP4 с помощью ffmpeg
в файле синтаксического анализа атома и сравнил их:
Первое, что бросилось мне в глаза, это то, что файл, сгенерированный ffmpeg
, содержит несколько видеосэмплов на moof
. В частности, каждый moof
начинался с 1 ключевого кадра, затем содержал все разностные кадры до следующего ключевого кадра (который использовался как начало следующего атома moof
).
Сравните это с тем, как я создаю свой MP4. Я создаю атом moof
каждый раз, когда приходит пакет FLV VIDEODATA
. Это означает, что мой moof
может не содержать ключевого кадра (и обычно его нет)
Может из-за этого у меня проблемы? Или есть что-то еще, что мне не хватает?
Видеофайлы, о которых идет речь, можно скачать здесь:
Другой проблемой, которую я заметил, было плодотворное использование ffmpeg
base_data_offset
в атоме tfhd
. Однако, когда я попытался отследить общее количество добавленных байтов и самостоятельно установить base_data_offset
, я получил сообщение об ошибке в Chrome в следующем виде: «MSE не поддерживает base_data_offset». Согласно спецификации ISO/IEC 14996-10:
Если не указано, смещение базовых данных для первой дорожки во фрагменте фильма является позицией первого байта охватывающего поля фрагмента фильма, а для второго и последующих фрагментов дорожки по умолчанию используется конец данных, определенных параметром предыдущий фрагмент.
Эта формулировка приводит меня к мысли, что data_offset
в первом атоме trun
должно быть равно размеру атома moof
, а data_offset
во втором атоме trun
должно быть 0
(0 байт с конца данных, определенных предыдущим фрагментом). . Однако, когда я попробовал это, я получил ошибку, что видеоданные не могут быть проанализированы. Что действительно привело к данным, которые можно было проанализировать, так это длина атома moof
плюс общая длина первой дорожки (как если бы базовое смещение было первым байтом закрывающая коробку moof
, такая же, как и первая дорожка)