LINUX.ORG.RU

Написать muxer потоков в AVI

 , ,


0

1

Здравствуйте, задался тут целью написать мьюксер, объединяющий видео и аудио потоки в контейнер. Решил выбрать AVI как наиболее простой и перспективный для моих задач вариант. Спецификацию контейнера AVI прочитал, реальные авишки в HEX редакторе поковырял... Но всё равно не понимаю, что делать дальше.

Есть ряд вопросов.

1) Что со структурой потока? Я так понимаю, в чанке должно в идеале быть целое число кадров? Как парсить кадры из сырого H264 потока?

2) Аналогично - мне неизвестна структура AAC потока (кодировщик - Nero Encoder). Если можете описать вкратце и на русском, буду признателен (сайт про AAC на английском читать пробовал, там не очень понятно).

3) Как делать корректную синхронизацию (по какому принципу разбивать звуковую дорожку)?

4) Может ли кадр быть распределён по нескольким чанкам? Я посмотрел размер чанков в AVI, которое формирует ffmpeg, так вот при битрейте 15 мбит/с (такой битрейт я по факту использую) у меня получается, что для записи одного видеокадра примерно 16 чанков понадобится...

Почему не использовать готовые решения? Всё просто - мне нужна возможность добавлять данные в контейнер «на лету», в процессе кодирования... Конечная цель - попытаться сделать кодирование с одновременной загрузкой на YouTube.

Индекс в AVI пишется в конце, так что тут ОК. С размерами будет шляпа - это да, заранее размер списков не просчитать. Но мне кажется, ютьюб это восстановит, это типичная ситуация, когда AVI файл недописан - обычно он всё равно воспроизводится, только перемотка не работает. С Bandicam проверял, и там даже есть утилита, восстанавливающая индекс, как раз для таких случаев :)



Последнее исправление: popov654 (всего исправлений: 2)

Youtube принимает stream по rtsp, тебе не нужен avi. Муксеры готовые возьми в ffmpeg и там же посмотри как синхронизировать, английский не забудь.

anonymous
()
Ответ на: комментарий от anonymous

Можно поподробнее про синхронизацию? В данный момент я имею нечто странное: при проигрывании AVI файла, экспортируемого из Эдика в Lossless (40 минут весят примерно 60 гигабайт) при воспроизведении в WMP (стоит K-Lite Codec Pack с соответствующими сплиттерами) - с синхронизацией полная жесть, её просто нет. Звук начинает отставать, и чем дальше от начала, тем сильнее. Если сразу перейти на середину файла - то сразу играет совсем не тот фрагмент аудиодорожки.

После конвертации через MediaCoder - всё супер (в качестве мультиплексора вроде как ffmpeg для AVI используется, могу скинуть MediaInfo). После конвертации через FormatFactory (видеокодек тот же, но мультиплексор - уже MEncoder) - синхронизация нарушена, звук отстаёт примерно на полсекунды (в MPC-HC и VLC). Не знаю, что будет после заливки на YouTube, но меня это уже напрягает (файлы локально тоже нужны для просмотра в дальнейшем). Поэтому надо либо написать идеальный код, либо ffmpeg юзать.

По поводу предложенного вами варианта - а в этом случае точно с синхронизацией будет всё ок?

P.S. В MediaCoder и VLC есть же вроде как возможность стримить на удалённый источник... Узнать бы параметры (куда, например). Это ютьюбом документировано? Я до этого просто только через браузер загружал.

Мне эта прога виделась так: найти режим работы, когда мьюксер пишет в контейнер непрерывно (на чтение вроде этот контейнер открыть можно, проверял на примере FormatFactory/MEncoder, открывая в WinHEX, хотя плееры и ругаются на то, что файл занят другим приложением), написать прогу, которая будет переоткрывать этот файл раз в секунду или две, вычитывать новые данные с последней позиции, и отправлять на сервер YouTube.

Кстати - вы уверены, что там именно поток принимается? Я вот не очень. Как загрузка через старые браузеры работает, где нет никаких WebRTC? Там вроде как обычный файл идёт на вход (выбираемый через форму), и уже на сервере он перекодируется.

popov654
() автор топика
Ответ на: комментарий от anonymous

http://forums.goha.ru/showthread_82_0_t897157

Если вы про это - то это не то, что нужно. Во-первых, это годится только для тех каналов, где доступны стримы (больше 100 подписчиков и хорошая репутация). У меня вот пока нет 100 подписчиков, и что мне теперь.

Во-вторых - эта возможность была создана ютубом совсем для другого.

В-третьих - это решение идеологически неверно. Да, на моём компе скорость кодирования видео в Full HD в H264 - примерно риалтайм, но это лишь совпадение. У кого-то быстрее, у кого-то медленнее. Поток же (я так думаю) всегда должен поступать на YouTube в риалтайме, чтобы он считался легитимным, иначе наверняка сервер посчитает, что что-то не так.

Есть мощные компы, где кодируется быстрее, есть слабые компы, где кодируется ещё медленнее. Инет тоже у всех разный.

Понимаете, мой подход хорош тем, что к риалтайму (фактической длительности видео) не привязан. Просто берём наименьшее из двух значений (между скоростью передачи данных и скоростью конвертации), немного его уменьшаем для создания запаса надёжности в случае, если скорость кодирования меньше, и посылаем байты. И всё.

Кстати, я проверял, незаконченные авишки почти прекрасно принимаются ютубом (разве что, обработка идёт чуть дольше, а в остальном ноль отличий).

И вообще, софта для ведения стримов (для того же Twitch) написано уже предостаточно. Но программы, которая бы выполняла конвертирование с одновременной загрузкой (дабы сократить время и повысить продуктивность работы ютуберов), я ещё не встречал.

popov654
() автор топика

Итого, вопрос сводится к следующему - а можно ли как-то использовать тот же мультиплексор, что использует для AVI MediaCoder, но заставить его писать AVI не в конце, а непрерывно, прямо в процессе кодирования потоков? Или только пилить аналог?

Кстати, вот MediaInfo файла, где с синхронизацией всё хорошо:

General
Complete name                            : G:\Game\HL1\series6.avi
Format                                   : AVI
Format/Info                              : Audio Video Interleave
Format profile                           : OpenDML
File size                                : 3.27 GiB
Duration                                 : 32mn 55s
Overall bit rate                         : 14.2 Mbps
Writing application                      : Lavf55.33.100

Video
ID                                       : 0
Format                                   : AVC
Format/Info                              : Advanced Video Codec
Format profile                           : High@L3
Format settings, CABAC                   : Yes
Format settings, ReFrames                : 1 frame
Codec ID                                 : H264
Duration                                 : 32mn 55s
Bit rate                                 : 14.0 Mbps
Width                                    : 1 920 pixels
Height                                   : 1 080 pixels
Display aspect ratio                     : 16:9
Frame rate                               : 30.000 fps
Color space                              : YUV
Chroma subsampling                       : 4:2:0
Bit depth                                : 8 bits
Scan type                                : Progressive
Bits/(Pixel*Frame)                       : 0.225
Stream size                              : 3.22 GiB (98%)
Writing library                          : x264 core 142 r2479kMod dd79a61
Encoding settings                        : cabac=1 / ref=1 / deblock=1:0:0 / analyse=0x3:0x133 / me=hex / subme=7 / psy=1 / fade_compensate=0.00 / psy_rd=1.00:0.00 / mixed_ref=0 / me_range=16 / chroma_me=1 / trellis=1 / 8x8dct=1 / cqm=0 / deadzone=21,11 / fast_pskip=1 / chroma_qp_offset=-2 / threads=7 / lookahead_threads=1 / sliced_threads=0 / nr=0 / decimate=1 / interlaced=0 / bluray_compat=0 / constrained_intra=0 / fgo=0 / bframes=0 / weightp=2 / keyint=250 / keyint_min=25 / scenecut=40 / intra_refresh=0 / rc_lookahead=40 / rc=abr / mbtree=1 / bitrate=14000 / ratetol=1.0 / qcomp=0.60 / qpmin=0 / qpmax=69 / qpstep=4 / ip_ratio=1.40 / aq=1:1.00

Audio
ID                                       : 1
Format                                   : AAC
Format/Info                              : Advanced Audio Codec
Format profile                           : LC
Codec ID                                 : FF
Duration                                 : 32mn 55s
Bit rate                                 : 224 Kbps
Channel(s)                               : 2 channels
Channel positions                        : Front: L R
Sampling rate                            : 48.0 KHz
Compression mode                         : Lossy
Stream size                              : 52.8 MiB (2%)
Alignment                                : Split accross interleaves
Interleave, duration                     : 21 ms (0.64 video frame)

А вот файл, где звук на половину или треть секунды запаздывает:

General
Complete name                            : G:\film~1.avi
Format                                   : AVI
Format/Info                              : Audio Video Interleave
Format profile                           : OpenDML
File size                                : 4.89 GiB
Duration                                 : 32mn 55s
Overall bit rate                         : 21.3 Mbps
Writing application                      : MEncoder SVN-r30881(20100311-gcc4.3.3)
Writing library                          : MPlayer

Video
ID                                       : 0
Format                                   : AVC
Format/Info                              : Advanced Video Codec
Format profile                           : High@L5
Format settings, CABAC                   : Yes
Format settings, ReFrames                : 1 frame
Codec ID                                 : avc1
Duration                                 : 32mn 55s
Bit rate                                 : 20.7 Mbps
Width                                    : 1 920 pixels
Height                                   : 1 080 pixels
Display aspect ratio                     : 16:9
Frame rate                               : 30.000 fps
Color space                              : YUV
Chroma subsampling                       : 4:2:0
Bit depth                                : 8 bits
Scan type                                : Progressive
Bits/(Pixel*Frame)                       : 0.333
Stream size                              : 4.86 GiB (99%)
Writing library                          : x264 core 80 r1378+57 6f6b50a
Encoding settings                        : cabac=1 / ref=1 / deblock=1:0:0 / analyse=0x3:0x113 / me=hex / subme=7 / psy=1 / psy_rd=1.0:0.0 / mixed_ref=0 / me_range=16 / chroma_me=1 / trellis=1 / 8x8dct=1 / cqm=0 / deadzone=21,11 / fast_pskip=1 / chroma_qp_offset=-2 / threads=6 / sliced_threads=0 / nr=0 / decimate=1 / mbaff=0 / constrained_intra=0 / bframes=0 / wpredp=2 / keyint=250 / keyint_min=25 / scenecut=40 / rc_lookahead=40 / rc=abr / mbtree=1 / bitrate=20736 / ratetol=1.0 / qcomp=0.60 / qpmin=10 / qpmax=51 / qpstep=4 / ip_ratio=1.40 / aq=1:1.00

Audio
ID                                       : 1
Format                                   : MPEG Audio
Format version                           : Version 1
Format profile                           : Layer 3
Mode                                     : Joint stereo
Mode extension                           : MS Stereo
Codec ID                                 : 55
Codec ID/Hint                            : MP3
Duration                                 : 32mn 54s
Bit rate mode                            : Constant
Bit rate                                 : 128 Kbps
Channel(s)                               : 2 channels
Sampling rate                            : 44.1 KHz
Compression mode                         : Lossy
Stream size                              : 30.1 MiB (1%)
Alignment                                : Aligned on interleaves
Interleave, duration                     : 26 ms (0.78 video frame)
Interleave, preload duration             : 522 ms
Writing library                          : LAME3.98
popov654
() автор топика
Ответ на: комментарий от gag

Спасибо, но нужно совсем не то :)

На самом деле, я уже разобрался. Надо просто вызывать ffmpeg и кодировать сразу им. Он создаёт AVI сразу, и дописывает его в процессе. Но тогда не выйдет звук конвертировать с помощью Nero Encoder... Вот линк: https://ffmpeg.zeranoe.com/forum/viewtopic.php?t=2054

Попробовал стандартный AAC кодировщик - в целом всё неплохо, но звук получается несколько более глухим и тихим. Зато помягче, и даже сгладились «перегрузки», где голос был слишком громко. Для ютьюба имхо это даже плюс.

Итого, что мне осталось: поскольку браузер читает в оперативную память файл единожды (или просто запоминает длину, что вероятнее), получается так, что он грузит ровно тот участок, что был готов на момент выбора файла в форме (что происходит там «под капотом» я точно не знаю, опять же).

Хорошая новость в том, что надо всего лишь написать загрузчик на любом языке. Дабы сильно не париться, можно использовать обычный YouTube API, а не эмулировать браузер, как я изначально хотел.

Есть ещё тонкость - мне бы научить мой будущий код определять фактическую скорость кодирования. ffmpeg выводит в консоль текущий fps, сейчас буду гуглить, можно ли эти данные как-то перехватить... Перенаправить stdout иными словами. Заодно и скрыть консоль бы не помешало, если всё это будет вызываться из GUI.

popov654
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.