Javascript MediaSource API и видео H264 - PullRequest
0 голосов
/ 31 мая 2018

У меня проблема с воспроизведением видео H264 с использованием API расширения MediaSource для JavaScript.

Я опишу сценарий с подробностями ниже.

Я уже успешно достиг результата, воспроизводящего аудио и видео источник кодека vp8, vp9, opus и vorbis, также из запроса диапазона(если сервер имеет возможность, используя любой диапазон байтов) или фрагментированные файлы, фрагменты выполняются с помощью Shaka Packager.

Проблема возникает, когда источником является видео H264, в моем случае кодеки avc1.64001e иmp4a.40.2, полная строка кодека: video / mp4; codecs = "avc1.64001e, mp4a.40.2", но проблема по-прежнему возникает с любым другим кодеком avc1.

Я пытаюсь сыграть10-мегабайтный фрагмент полного видео, порция, сгенерированная запросом curt в байтовом диапазоне, с локальным сохранением ответа с использованием -o.

Ниже информации о потоке от упаковщика shaka, передающего этот файл в качестве входных данных

[0530/161459:INFO:demuxer.cc(88)] Demuxer::Run() on file '10mega.mp4'.
[0530/161459:INFO:demuxer.cc(160)] Initialize Demuxer for file '10mega.mp4'.

File "10mega.mp4":
Found 2 stream(s).
Stream [0] type: Video
 codec_string: avc1.64001e
 time_scale: 17595
 duration: 57805440 (3285.3 seconds)
 is_encrypted: false
 codec: H264
 width: 720
 height: 384
 pixel_aspect_ratio: 1:1
 trick_play_factor: 0
 nalu_length_size: 4

Stream [1] type: Audio
 codec_string: mp4a.40.2
 time_scale: 44100
 duration: 144883809 (3285.3 seconds)
 is_encrypted: false
 codec: AAC
 sample_bits: 16
 num_channels: 2
 sampling_frequency: 44100
 language: und

Packaging completed successfully.

Чанк можно воспроизводить с помощью приложений внешнего медиаплеера (например, VLC), и, что более важно, он воспроизводится без проблем, добавляя его на веб-страницу с помощью tag.

Это ошибка, которую я вижу в консоли Chrome

Uncaught (in promise) DOMException: Failed to load because no supported source was found.

Здесь ниже html и js-код, если вы хотите воспроизвести (я сделал все локальные тесты, используявстроенный сервер php7.2 dev)

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <title>VideoTest</title>
    <link rel="icon" href="/favicon.ico" />
    <script type="text/javascript" src="/script.js"></script>

    <style>
        video {
            width: 98%;
            height: 300px;
            border: 0px solid #000;
            display: flex;
        }
    </style>
</head>
<body>

<div id="videoContainer">
    <video controls></video>
</div>

<video controls>
    <source src="/media/10mega.mp4" type="video/mp4">
</video>

</body>
</html>

А вот ниже код JS (scripjs)

class MediaTest {
    constructor() {

    }

    init(link) {
        this.link = link;
        this.media = new MediaSource();
        this.container = document.getElementsByTagName('video')[0];
        this.container.src = window.URL.createObjectURL(this.media);

        return new Promise(resolve => {
            this.media.addEventListener('sourceopen', (e) => {
                this.media = e.target;
                return resolve(this);
            });
        });
    }

    addSourceBuffer() {
        let codec = 'video/mp4;codecs="avc1.64001e, mp4a.40.2"';
        let sourceBuffer = this.media.addSourceBuffer(codec);

        // These are the same headers sent by the < source > tag
        // with or without the issue remains
        let headers = new Headers({
            'Range': 'bytes=0-131072',
            'Accept-Encoding': 'identity;q=1, *;q=0'
        });

        let requestData = {
            headers: headers
        };
        let request = new Request(this.link, requestData);

        return new Promise(resolve => {
            fetch(request).then((response) => {
                if(200 !== response.status) {
                    throw new Error('addSourceBuffer error with status ' + response.status);
                }

                return response.arrayBuffer();
            }).then((buffer) => {
                sourceBuffer.appendBuffer(buffer);
                console.log('Buffer appended');
                return resolve(this);
            }).catch(function(e) {
                console.log('addSourceBuffer error');
                console.log(e);
            });
        });
    }

    play() {
        this.container.play();
    }
}

window.addEventListener('load', () => {
    let media = new MediaTest();
    media.init('/media/10mega.mp4').then(() => {
        console.log('init ok');
        return media.addSourceBuffer();
    }).then((obj) => {
        console.log('play');
        media.play();
    });
});

Чего я хочу добиться - это воспроизвести файл с помощью MediaSource APIтак как он играет хорошо, используя тег

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

Здесь ниже дамп ошибок, полученный из chrome: // media-internals

render_id: 180 player_id: 11 pipeline_state: kStopped событие: WEBMEDIAPLAYER_DESTROYED

Для воспроизведения, я думаю, можно использовать любое видео H264, в котором есть аудио и видео дорожка.

Этот вопрос строго связан с другим вопросом, который я нашел Видео H264 работает с использованием атрибута src.В том же видео не удается использовать MediaSource API (Chromium) , но это сделано 4 года назад, поэтому я решил не отвечать на него.

Кто-нибудь имеет представление об этой проблеме?Есть ли способ ее решить или h264 просто не совместим с MSE?

Заранее спасибо

1 Ответ

0 голосов
/ 31 мая 2018

Это не кодек, это контейнер.MSE требует фрагментированных файлов mp4.Стандартный mp4 не поддерживается.для стандартного mp4 вы должны использовать <video src="my.mp4">

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...