Прямая трансляция содержимого тире с использованием mp4box

Я пытаюсь транслировать контент H.264 в режиме реального времени на HTML5 с помощью API расширений источника мультимедиа.

Следующий метод работает довольно хорошо:

ffmpeg -i rtsp://10.50.1.29/media/video1 -vcodec copy -f mp4 -reset_timestamps 1 -movflags frag_keyframe+empty_moov -loglevel quiet out.mp4

а потом: mp4box -dash 1000 -frag 1000 -frag-rap out.mp4

Я могу взять вывод MP4Box (out_dashinit.mp4) и отправить его через веб-сокеты, фрагмент за фрагментом, клиенту JavaScript, который передает его в API источника мультимедиа.

Однако это не лучший метод для живого контента.

Что я пытаюсь сделать сейчас, так это создать единый конвейер, чтобы делать это в реальном времени и с минимально возможной задержкой. С FFmpeg можно перенаправить вывод на stdout вместо out.mp4 и получить содержимое. Я не мог понять, можно ли объединить MP4Box в конвейер.

  1. Может ли MP4Box брать входные данные из источника, который не является файлом?
  2. Может ли MP4Box захватывать такой контент постепенно (из файла или другого источника), пока он поступает в режиме реального времени? т.е. подождите немного, если поток остановится на 1 секунду и возобновится автоматически.
  3. Тот же вопрос, но для вывода: может ли он выводиться во что-то, что не является файлом (например, stdout), и может ли он делать это постепенно, чтобы всякий раз, когда выходные данные будут готовы, я мог взять их и передать в веб-клиент. , по сути, создавая бесконечный пунктирный MP4.

person galbarm    schedule 03.06.2015    source источник


Ответы (2)


Вам не нужен MP4Box для создания требуемого вывода, но вам нужно будет самостоятельно разбить содержимое на блоки и найти блоки в сгенерированном файле.

В основном вы создаете fMP4 с H264 и отправляете в браузер поле moov для инициализации и поля moof+mdat для каждого фрагмента MP4, который вы создаете. Вам придется кодировать проигрыватель на JavaScript, вы, вероятно, не сможете использовать стандартный проигрыватель DASH.

Чтобы сгенерировать правильный фрагментированный MP4, вам нужно передать это в ffmpeg: -movflags empty_moov+omit_tfhd_offset+frag_keyframe+default_base_moof.

Обязательно используйте последнюю доступную версию.

person Pablo Montilla    schedule 04.06.2015
comment
фантастический. Оно работает! У вас также есть предложение по уменьшению задержки? В настоящее время у меня около 3-4 секунд задержки - person galbarm; 04.06.2015
comment
Приходится работать с параметрами, доступными для x264. Первое, что я проверю, это -tune zerolatency, и буду двигаться дальше. - person Pablo Montilla; 04.06.2015
comment
Но я не перекодирую видео. Как видите, я использую -vcodec copy и точно знаю, что видео приходит практически с нулевой задержкой. - person galbarm; 04.06.2015
comment
Кроме того, я только что узнал, что есть профиль dash для прямой трансляции (urn:mpeg:dash:profile:isoff-live:2011), так что, возможно, вы можете настроить вывод и использовать для этого стандартный проигрыватель. - person Pablo Montilla; 04.06.2015
comment
Теперь я вижу, что вы копируете видео... Тогда я не знаю... ;) У вас не должно быть большой задержки. Попробуйте изменить -frag_duration на небольшое значение, возможно, таким образом у вас будет меньше задержек. - person Pablo Montilla; 04.06.2015
comment
Камера отправляет видео с интервалом между ключевыми кадрами ровно 1 сек. Поскольку я использую frag_keyframe, я ожидаю, что задержка составит примерно 1 секунду + небольшая дельта. frag_duration не помог. Я буду продолжать исследовать и обновлять, если я найду что-то. - person galbarm; 04.06.2015
comment
galbarm Не могли бы вы опубликовать полные команды ffmpeg и mp4box, которые вы, наконец, используете? У меня похожая среда, и я не могу воспроизвести видео с помощью медиаисточника. Я предполагаю, что я не правильно кодирую. - person Silvia; 12.06.2015
comment
@Silvia Как предложил Пабло, я больше не использую MP4box, так как все настроил с помощью ffmpeg. Я все еще борюсь с проблемой задержки, но в остальном все работает хорошо. Команда ffmpeg: ffmpeg -i rtsp://172.20.28.52:554/h264 -vcodec copy -an -f mp4 -reset_timestamps 1 -movflags empty_moov+default_base_moof+frag_keyframe -loglevel quiet - я получаю вывод ffmpeg через стандартный вывод и транслировать его в Интернет с помощью веб-сокетов - person galbarm; 14.06.2015
comment
Я разместил дополнительный вопрос о проблеме с задержкой здесь: stackoverflow.com/questions/30868854/ - person galbarm; 16.06.2015
comment
@gelbarm Какую библиотеку вы используете на стороне клиента (JS)? Просто рисовать на холсте? Не могли бы вы предоставить код? Спасибо. - person Zsolt; 31.08.2015
comment
@gelbarm Нужно ли вам каким-либо образом разделять кадры (например, ровно один фрагмент MP4 на кадр), когда вы отправляете их через веб-сокет? или любое количество байтов будет работать, поскольку видео/MediaSource правильно реконструирует фрагменты? Я пытаюсь сделать то же самое, но это работает только в 10% случаев. - person Philippe Cayouette; 11.09.2015
comment
@PhilippeCayouette вам нужно сделать это на уровне фрагмента. В основном вы можете анализировать поток закодированных байтов в границах блоков и отправлять блоки moof+mdat. Это может быть проанализировано объектом источника мультимедиа, как только вы его правильно инициализируете (с полем moov). - person Pablo Montilla; 11.09.2015
comment
@PabloMontilla Я последовал вашему предложению, захватив блок moov в начале потока и отправив этот блок moov любому новому клиенту, а затем текущие блоки moof + mdat. Похоже, это не работает с внутренним видеоплеером Chrome (однако VLC может воспроизводить файл с такой дырой между moov и первым moof + mdat). В хроме работает только тогда, когда в последовательности moof+mdat нет дыр. Я даже пытался изменить порядковый номер moof, чтобы он начинался с 1 и увеличивался монотонно, но безрезультатно. Какие-либо предложения? - person Philippe Cayouette; 12.09.2015
comment
@PhilippeCayouette, вы можете покопаться в chrome://media-internals и посмотреть, есть ли там ошибка. Chrome немного требователен к профилю кодировщика, который он может использовать при использовании MSE. Файл может корректно воспроизводиться в ‹video/› и совсем не воспроизводится в MSE. - person Pablo Montilla; 12.09.2015
comment
@PhilippeCayouette также обязательно отправьте добавление только к блоку moov, а затем к паре блоков мультимедиа. - person Pablo Montilla; 12.09.2015
comment
@PabloMontilla, не могли бы вы поделиться способом разделения потока на фрагменты moov/moof+dat, чтобы правильно отправить их клиенту? - person Jamby; 12.06.2016
comment
Это не сложно, но и не тривиально. Я бы начал с рассмотрения структуры формата файла BMFF (это то, что вы отправляете клиенту). По сути, это поток ящиков с type, length и content (которые могут быть самими ящиками). Если вы можете разобрать эту структуру, вы в основном настроены так, что отправка правильных боксеров в тандеме не является проблемой. - person Pablo Montilla; 13.06.2016
comment
@PabloMontilla Я немного опаздываю на вечеринку, но я работаю именно над этим. За исключением того, что я планирую отправлять данные с помощью RTCDataChannel (по сути, UDP) вместо WebSockets, что технически должно дать мне еще большую задержку. Я новичок во всех этих видеоматериалах, и мне очень трудно понять все эти разговоры о moof, mdat и moov и о том, что мне нужно делать с фрагментами mp4, которые я получаю, прежде чем передавать их в SourceBuffer. Можете ли вы дать некоторые рекомендации? - person snowfrogdev; 08.01.2019
comment
Сейчас я не знаком с компьютером, но если вы найдете описание формата файла BMFF, вы обнаружите, что это «легкий» для анализа формат, состоящий из «блоков» с типом и данными. Как только вы сможете разобрать этот формат, вы можете начать отправлять пакеты с правильной структурой, которая будет использоваться с исходным буфером. Использование RTCDataChannel не должно быть проблемой и должно уменьшить задержку (это не вариант, когда я выполнял эту работу). - person Pablo Montilla; 08.01.2019

Насколько я понимаю ваше решение, вы не транслируете, а постепенно загружаете один файл MP4. Я правильно это понимаю?

Недавно я запустил проект RTP2DASH, чтобы выполнять настоящую прямую трансляцию DASH из источника данных RTP. Это все еще очень «альфа», но его легко адаптировать для простых случаев использования.

person Sebastian Annies    schedule 11.09.2015
comment
Нет. Мое решение — это действительно потоковое видео. Хотя содержимое данных представляет собой фрагментированный формат mp4, данные никогда не записываются в файл. - person galbarm; 14.09.2015
comment
Я понял это, но все же это не DASH, верно? Нет ни Манифеста, ни множественных качеств. Он преобразует поток RTSP в прогрессивную загрузку. - person Sebastian Annies; 14.09.2015
comment
Верный. Это не адаптивное потоковое решение. Это минимально возможная задержка - единственное качественное решение. - person galbarm; 15.09.2015
comment
Одним из преимуществ является то, что для такого решения не требуется транскодирование. Это очень легко. Потенциально вы можете транслировать сотни потоков с одного сервера. - person galbarm; 15.09.2015
comment
в моем предложении транскодирование также не требуется, НО вы получаете поток DASH. У меня сложилось впечатление, что использование DASH было своего рода требованием — конечно, если вы выполняете прогрессивную загрузку с тегом видео HTML5, это настолько легковесно, насколько это возможно. Я познакомился с ребятами из mistserver.org на IBC. Их презентация в прошлом году была именно тем способом, которым вы можете стримить на несколько сотен клиентов с Raspberry Pi. Может стоит посмотреть! - person Sebastian Annies; 16.09.2015