Как я могу услышать звук при очистке звука с тега <audio>? - PullRequest
1 голос
/ 06 февраля 2020

В моем примере у меня есть mp3, который пользователь загрузил на веб-страницу. Я создаю визуальную форму волны на странице, и все стандартные элементы управления закодированы и работают (воспроизведение, пауза, остановка, очистка и т. Д. c ...)

Что я пытаюсь выполнить sh это эффект очистки, который вы слышите в After Effects или Animate. Когда я чищу звук, я хочу услышать тоны звука именно там, где находится скруббер.

Я даже не знаю, с чего начать? Я посмотрел на AudioContext и думаю, что мой ответ где-то там, но я не уверен. Я думал о том, чтобы иметь «теневую звуковую метку», для которой я устанавливаю тот же sr c, а затем вызываю play() и довольно скоро приостанавливаю его, но это кажется беспорядком; особенно с агрессивным скруббером. Любое направление будет оценено!

Ответы [ 2 ]

1 голос
/ 07 февраля 2020

Да, ваш ответ в API AudioContext (все asyn c и медленные MediaElements не предназначены для этого). В частности, вам нужен интерфейс AudioBufferSourceNode , который способен мгновенно воспроизводить аудио.

Все, что вам нужно сделать, - это извлечь ваш аудиофайл в виде ArrayBuffer, попросить AudioContext для декодирует данные PCM аудио из этого буфера и создает из него аудиобуфер.

Это была тяжелая часть, но это делается только один раз.

Тогда вам просто нужно создать очень легкий AudioBufferSourceNode для каждого события "scrub".
Для этого вы можете использовать версию с тремя аргументами start(when, offset, duration) метод.

const slider = document.getElementById('slider');
const ctx = new AudioContext();

fetch("https://upload.wikimedia.org/wikipedia/en/d/dc/Strawberry_Fields_Forever_(Beatles_song_-_sample).ogg")
  .then( resp => resp.arrayBuffer() )
  .then( buf => ctx.decodeAudioData(buf) )
  .then( prepareUI )
  .catch( console.error );
  
function prepareUI( audioBuf ) {
  let source;
  slider.oninput = e => {
    if( source ) { source.stop(0); }
    source = ctx.createBufferSource();
    source.buffer = audioBuf;
    source.connect(ctx.destination);
    const offset = slider.value * audioBuf.duration;
    const duration = 0.1;
    source.start(0, offset, duration);
  };
  slider.disabled = false;
}
input { width: 350px }
<input type="range" id="slider" min="0" max="1" step="0.005" disabled>

И, конечно, вы также можете повторно использовать этот AudioBuffer для всего вашего проигрывателя.

1 голос
/ 07 февраля 2020

Я думаю, что вы на правильном пути. Ваш пользовательский интерфейс скруббера может взаимодействовать с элементом Audio, который не присоединен к DOM / странице и может напрямую устанавливать audio.currentTime, воспроизводиться в течение нескольких миллисекунд и затем останавливаться. Вы можете использовать отмену очередей setTimeout() для создания коротких воспроизведений с очисткой, а затем непрерывно воспроизводить, когда очистка прекращается. Я предполагаю, что все это зависит от загружаемого файла целиком, чтобы избежать задержки в сети во время очистки.

...