потоковая передача файла mkv при обработке с помощью ffmpeg - PullRequest
0 голосов
/ 01 апреля 2019

Что я хочу сделать:

  • Я хочу воспроизвести видео в формате mkv в Firefox.
  • Но Firefox не поддерживает формат mkv.

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

  • mkv можно преобразовать в m3u8 с помощью FFmpeg
  • m3u8 указывает на файлы сегментов ts
  • , затем используйте hls.js на стороне браузера для воспроизведения видео

Но загвоздка в том, что я хочу сделать этопрограммно.

Что я на самом деле хочу сделать:

Steps

  • клиент загружает огромные (> 1 ГБ)MKV-файл на сервер клиента (сервер - это компьютер клиента)

  • после завершения загрузки

  • клиент запрашивает воспроизведение видео.

  • сервер начинает транскодирование и немедленно отправляет клиенту поток m3u8 вместо того, чтобы заставлять клиента ждать транскодирование to завершено.

  • клиент должен иметь возможность искать видео.(самая ВАЖНАЯ часть)

Это возможно, поскольку Emby и Plex оба реализовали это.

Я былвозможность заставить это работать в Chrome, поскольку он поддерживает воспроизведение некоторых файлов MKV.Я написал сервер узла js, который принимает заголовок Range и псевдопотоков видео.

Суть

Но, как яупомянутый Firefox говорит «нет» mkv.

Так что я попробовал hls, но не смог получить команду для генерации потока и воспроизведения на лету.

Я начал это накомандная строка

ffmpeg -i ../stream.mkv -hls_list_size 0 -acodec copy -vcodec copy file.m3u8

и простой http-server на другом экземпляре оболочки

Мой файл index.html

<html>
    <title>Welcome</title>
    <body>
        <script src="./hls.js"></script>
        <video id="video" width="400" controls></video>
        <script>
            var video = document.getElementById('video');
            if(Hls.isSupported()) {
                var hls = new Hls();
                hls.loadSource('file.m3u8');
                hls.attachMedia(video);
                hls.on(Hls.Events.MANIFEST_PARSED,function() {
                    video.play();
                });
            } else if (video.canPlayType('application/vnd.apple.mpegurl')) {
                video.src = 'file.m3u8';
                video.addEventListener('loadedmetadata',function() {
                    video.play();
                });
            }
        </script>
    </body>
</html>

, и пока он работал, я продолжил изапросил сервер.

Мне удалось получить видео, но оно только ищет, насколько оно конвертировано в файлы ts.

И это случайно, и длина видео продолжает увеличиваться.Иногда он не воспроизводится, и после того, как FFmpeg завершит преобразование в m3u8, видео будет воспроизводиться, если я обновлю веб-страницу.

Я думаю, что это связано с непрерывной перезаписью файла m3u8.Есть ли способ предопределить содержимое файла m3u8 и заполнить его?

Я хочу иметь возможность искать еще дальше и как-то порождать другой процесс FFmpeg, чтобы начать с этой отметки времени видео?Как я могу подойти к поисковой части?

Итак, я бы хотел сделать еще раз:

  • Я хочу попросить сервер воспроизвести видеофайл
  • Он порождает дочерний процесс FFmpeg, который выполняет транскодирование
  • Отправляет клиенту поток
  • Клиент должен иметь возможность искать до конца, и он должен играть вещь.

1 Ответ

1 голос
/ 02 апреля 2019

Эта проблема на самом деле очень сложная. Plex может обманывать, потому что файл упакован специально для каждого пользователя, и по большей части плекс управляет плеером.

Принцип работы Plex:

Файл предварительно анализируется, и создается полный манифест. Transcode запускается в начале файла и кэширует сегменты локально. Если происходит поиск (запрашивается сегмент, который не кэшируется локально), транскод отменяется, и начинается новый запуск со смещением запрошенного сегмента, и проигрыватель делает недействительным любой сегмент, который он кэшировал.

Если клиентские кэшированные сегменты не признаны недействительными или используется CDN, нет никакой гарантии, что первый сегмент после поиска будет выровнен с предыдущим сегментом, сгенерированным позднее. Это приведет к пропуску и появлению на границе.

Например, найдите в фильме 1 час, а затем пропустите 30 секунд назад. Два сегмента созданы в неправильном порядке и не будут воспроизводиться плавно

Если вам требуется поддержка готовых проигрывателей и CDN, проблема является более сложной, поскольку вы должны иметь возможность генерировать кадры с точностью до кадра на лету. Кадр с точным звуком сложен, особенно с кодеками, использующими примеры заправки. Я рекомендую вам взглянуть на коммерческие сервисы, такие как mux.com , которые в основном делают это.

...