@(аудио-видео)[Аудио|Видео|MSE]
Аудио и видеоС развитием Интернета все больше и больше требований к аудио и видео.Однако независимо от того, воспроизводятся ли аудио и видео или кодируются и декодируются, а к упаковке предъявляются высокие требования к производительности, что могут интерфейсные и аудио и видео поля делать на данном этапе?
[TOC]
Воспроизведение аудио или видео
html5 audio
Когда дело доходит до воспроизведения аудио и видео, первое, что приходит мне на ум, этоHTMLMediaElement,video
проиграть видео,audio
Воспроизвести аудио. Возьмите каштан:
<audio controls autoplay loop="true" preload="auto" src="audio.mp3"></audio>
-
controls
Укажите браузер для рендеринга в html5audio
. -
autoplay
Атрибут указывает браузеру автоматически воспроизводить файл . -
loop
Свойство зацикливается. -
preload
При рендеринге в аудиоэлемент загружается аудиофайл. - Мобильные браузеры не поддерживают
autoplay
а такжеpreload
свойство, то есть аудиофайл не будет загружаться автоматически, а будет вызван только некоторыми событиями, такими какtouch
,click
События и т. д. запускают загрузку, а затем воспроизведение. - Есть также некоторые элементы мультимедиа, которые изменяют громкость, определенное событие завершения воспроизведения звука и т. д., пожалуйста, прочитайтеHTMLMediaElement.
- Конечно, если ваша веб-страница работает в WebView, вы можете позволить клиенту установить некоторые свойства для предварительной загрузки и автоматического воспроизведения.
AudioContext
Хотя с использованием html5audio
Аудио может воспроизводиться, но, как вы можете видеть, есть много проблем, и в то же время я не могу очень хорошо управлять воспроизведением аудио, например, получать двоичные аудиоданные из сети, иногда я хочу последовательно воспроизвести несколько аудио , ибо использование аудиоэлементов тоже бессильно, да и не изящно в обращении.
Возьмите каштан:
function queuePlayAudio(sounds) {
let index = 0;
function recursivePlay(sounds, index) {
if(sounds.length == index) return;
sounds[index].play();
sounds[index].onended = recursivePlay.bind(this, sounds, ++index);
}
}
мониторaudio
элементальonended
события, играть последовательно.
Чтобы лучше контролировать воспроизведение звука, мне нужноAudioContext.
Интерфейс AudioContext представляет граф обработки звука, соединенный аудиомодулями, и каждый модуль соответствует AudioNode. AudioContext может управлять созданием содержащихся в нем узлов и выполнением операций обработки и декодирования звука. Прежде чем что-либо делать, создайте объект AudioContext, потому что все происходит в этом контексте.
Это может быть неясно для понимания. Проще говоря, AudioContext похож на фабрику. Для воспроизведения звука, от источника звука до управления звуком, до реализации оборудования для воспроизведения ссылок, все модули отвечают за обработку, и процесс реализуется через подключение управление.
Теперь я могу реализовать управление воспроизведением аудио, например, получать его из сети. Используйте AJAX для получения данных типа arraybuffer, декодируйте их, а затем передайте двоичные аудиоданные в BufferSourceNode, созданный AudioContext, и, наконец, передайте ссылкуdestination
Модуль реализует воспроизведение звука.
export default class PlaySoundWithAudioContext {
constructor() {
if(PlaySoundWithAudioContext.isSupportAudioContext()) {
this.duration = 0;
this.currentTime = 0;
this.nextTime = 0;
this.pending = [];
this.mutex = false;
this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
}
}
static isSupportAudioContext() {
return window.AudioContext || window.webkitAudioContext;
}
play(buffer) {
var source = this.audioContext.createBufferSource();
source.buffer = buffer;
source.connect(this.audioContext.destination);
source.start(this.nextTime);
this.nextTime += source.buffer.duration;
}
addChunks(buffer) {
this.pending.push(buffer);
let customer = () => {
if(!this.pending.length) return;
let buffer = this.pending.shift();
this.audioContext.decodeAudioData(buffer, buffer => {
this.play(buffer);
console.log(buffer)
if(this.pending.length) {
customer()
}
}, (err) => {
console.log('decode audio data error', err);
});
}
if(!this.mutex) {
this.mutex = true;
customer()
}
}
clearAll() {
this.duration = 0;
this.currentTime = 0;
this.nextTime = 0;
}
}
AJAX-вызов
function xhr() {
var XHR = new XMLHttpRequest();
XHR.open('GET', '//example.com/audio.mp3');
XHR.responseType = 'arraybuffer';
XHR.onreadystatechange = function(e) {
if(XHR.readyState == 4) {
if(XHR.status == 200) {
playSoundWithAudioContext.addChunks(XHR.response);
}
}
}
XHR.send();
}
Использование Ajax для воспроизведения нормально для небольшого аудиофайла, но для большого аудиофайла нереально дождаться завершения загрузки.Может ли он воспроизводиться во время загрузки. используйте это здесьfetchосуществлять загрузкуstream
поток.
fetch(url).then((res) => {
if(res.ok && (res.status >= 200 && res.status <= 299)) {
readData(res.body.getReader())
} else {
that.postMessage({type: constants.LOAD_ERROR})
}
})
function readData(reader) {
reader.read().then((result) => {
if(result.done) {
return;
}
console.log(result);
playSoundWithAudioContext.addChunks(result.value.buffer);
})
}
Проще говоря, этоfetch
изresponse
вернутьreadableStreamИнтерфейс, читая из него поток и непрерывно передавая его в audioContext для воспроизведения, тест показал, что мобильный терминал не может обеспечить плавное воспроизведение, но браузер ПК может.
PCM audio
При реализации воспроизведения audioContext мне нужно декодировать и использоватьdecodeAudioData
API реализует декодирование. Я знаю, что звук обычно сжимается в mp3, aac и другие форматы кодирования. Мне нужно декодировать его в данные PCM, прежде чем его можно будет воспроизвести. Что такое PCM? Я все знаю, что звук генерируется вибрацией предметов, но такие звуковые волны не могут быть сохранены и рассчитаны компьютером.Мне нужно использовать определенный способ описания звука, поэтому у меня есть данные в формате PCM, указывающие на частоту звук, собранный микрофоном. , количество собранных битов и количество каналов, стерео или моно.
Media Source Extensions
Media Source Extensionsможно задать динамическиAudio
а такжеVideo
Создайте поток для реализации воспроизведения. Короче говоря, он может хорошо управляться для воспроизведения. Например, он может реализовать функцию поиска при повторном воспроизведении. Он также может преобразовывать определенный формат для воспроизведения во внешнем интерфейсе, но не все форматы поддерживается.
Добавляя данные вSourceBuffer
, MSE сохраняет эти данные в буфере и декодирует их для воспроизведения. Вот простой пример использования MSE для воспроизведенияaudio
из каштанов:
export default class PlaySoundWithMSE{
constructor(audio) {
this.audio = audio;
if(PlaySoundWithMSE.isSupportMSE()) {
this.pendingBuffer = [];
this._mediaSource = new MediaSource();
this.audio.src = URL.createObjectURL(this._mediaSource);
this._mediaSource.addEventListener('sourceopen', () => {
this.sourcebuffer = this._mediaSource.addSourceBuffer('audio/mpeg');
this.sourcebuffer.addEventListener('updateend',
this.handleSourceBufferUpdateEnd.bind(this));
})
}
}
addBuffer(buffer) {
this.pendingBuffer.push(buffer);
}
handleSourceBufferUpdateEnd() {
if(this.pendingBuffer.length) {
this.sourcebuffer.appendBuffer(this.pendingBuffer.shift());
} else {
this._mediaSource.endOfStream();
}
}
static isSupportMSE() {
return !!window.MediaSource;
}
}
HTML5-плеер
Говоря о html5-плеерах, вы, возможно, знаете, что bilibiliflv.js, он использует расширения Media Source для переупаковки видео в формате кодирования FLV в формат mp4, а затем реализует воспроизведение.
Как видно из блок-схемы,IOController
Чтобы добиться загрузки потокового видео, поддержите здесьfetch
Возможность стримить,WebSocket
Подождите, полученный видеопоток, здесь относится к видеопотоку в формате flv, инкапсулируется в формат MP4, и, наконец, данные в формате MP4 передаются в MSE через appendBuffer для воспроизведения.
будущее
Все вышесказанное относится к воспроизведению видео.Вы также можете видеть, что, хотя существует много ограничений на воспроизведение, поддержка браузера MSE невелика.В областях кодирования и декодирования видео, которые требуют высокой производительности, может ли интерфейс что-то делать? Как насчет вещей? Причин низкой производительности фронтенда много.В среде песочницы, такой как браузер, и динамическом языке, таком как js, производительность не высока, поэтому какие-то большие парни предложили скомпилировать c++ в js, а потом улучшить производительность, может быть, вы уже знаете, что я хочу сказать, это ASM.js, который является строгим подмножеством js. Я Мэн могу рассмотреть возможность компиляции некоторых библиотек кодирования видео в js для повышения производительности, о чем следует упомянуть.FFmpeg, вы можете скомпилировать его в asm, а затем кодировать и декодировать видео.
напиши в конце
Я вижу, что интерфейс для обработки аудио и видео можно назвать тонким льдом по многим причинам, но при воспроизведении видео с поддержкой браузера он может быть активен.
Вербовка волхвов
Toutiao уже давно набирает большое количество фронтенд-инженеров, и вы можете выбирать из Пекина, Шэньчжэня, Шанхая, Сямэня и других городов. Добро пожаловать, чтобы отправить свое резюме наtcscyl@gmail.com / yanglei.yl@bytedance.com