Запись результата обработки аудио из буфера и помещение его в аудио элемент

У меня есть файл JavaScript, который берет аудиофайл, помещает его в буфер, а затем позволяет обрабатывать звук в буфере (путем изменения скорости и продолжительности цикла).

Я хочу записать полученный звук, включая манипуляции, и поместить его в элемент <audio>. Я попытался сделать это, интегрировав код, указанный в первом ответе здесь:

Запись звука аудиоконтекста webaudio API

с моим файлом JavaScript. Однако я получаю следующие ошибки, когда нажимаю кнопку воспроизведения (которая также должна начать запись):

GET http://localhost:8000/[object%20AudioBufferSourceNode] [HTTP/1.0 404 File not found 1ms] 

HTTP load failed with status 404. Load of media resource http://localhost:8000/[object%20AudioBufferSourceNode] failed. index.html

Uncaught (in promise) DOMException: The media resource indicated by the src attribute or assigned media provider object was not suitable.

Я считаю, что неправильно подключаю медиа-рекордер. Кто-нибудь может помочь?

Спасибо,

Мой html:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width">

    <title>decodeAudioData example</title>

    <link rel="stylesheet" href="">
    <!--[if lt IE 9]>
      <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
    <![endif]-->
  </head>

  <body>
    <h1>decodeAudioData example</h1>

    <button class="play">Play</button>
    <button class="stop">Stop</button>

    <h2>Set playback rate</h2>
    <input class="playback-rate-control" type="range" min="0.25" max="3" step="0.05" value="1">
    <span class="playback-rate-value">1.0</span>

    <h2>Set loop start and loop end</h2>
    <input class="loopstart-control" type="range" min="0" max="20" step="1" value="0">
    <span class="loopstart-value">0</span>

    <input class="loopend-control" type="range" min="0" max="20" step="1" value="0">
    <span class="loopend-value">0</span>

    <br>
    <br>

    <!--Audio recoring destination element-->
    <audio id='recording' controls='true'></audio>

  </body>
</html>

Мой JavaScript:

let audioCtx;
let source;
let songLength;

const pre = document.querySelector('pre');
const myScript = document.querySelector('script');
const play = document.querySelector('.play');
const stop = document.querySelector('.stop');

const playbackControl = document.querySelector('.playback-rate-control');
const playbackValue = document.querySelector('.playback-rate-value');
playbackControl.setAttribute('disabled', 'disabled');

const loopstartControl = document.querySelector('.loopstart-control');
const loopstartValue = document.querySelector('.loopstart-value');
loopstartControl.setAttribute('disabled', 'disabled');

const loopendControl = document.querySelector('.loopend-control');
const loopendValue = document.querySelector('.loopend-value');
loopendControl.setAttribute('disabled', 'disabled');

// Recording variables

var recorder=false;
var recordingstream=false;

// use XHR to load an audio track, and
// decodeAudioData to decode it and stick it in a buffer.
// Then we put the buffer into the source

function getData() {
  /*if(window.webkitAudioContext) {
    audioCtx = new window.webkitAudioContext();
  } else {
    audioCtx = new window.AudioContext();
  }*/
  audioCtx = new window.AudioContext();

  source = audioCtx.createBufferSource();
  request = new XMLHttpRequest();

  request.open('GET', 'precky.mp3', true);

  request.responseType = 'arraybuffer';


  request.onload = function() {
    let audioData = request.response;

    audioCtx.decodeAudioData(audioData, function(buffer) {
        myBuffer = buffer;
        songLength = buffer.duration;
        source.buffer = myBuffer;
        source.playbackRate.value = playbackControl.value;
        source.connect(audioCtx.destination);
        source.loop = true;

        loopstartControl.setAttribute('max', Math.floor(songLength));
        loopendControl.setAttribute('max', Math.floor(songLength));
      },

      function(e){"Error with decoding audio data" + e.error});

  }

  request.send();
}


function startrecording(){
    recordingstream=audioCtx.createMediaStreamDestination();
    recorder=new MediaRecorder(recordingstream.stream);
    recorder.start();
}

function glue(){
    let a=new Audio(source);
    let mediasource=audioCtx.createMediaElementSource(a);
    mediasource.connect(recordingstream);//connects also to MediaRecorder
    a.play();
} 

function stoprecording(){
  recorder.addEventListener('dataavailable',function(e){
   document.querySelector('#recording').src=URL.createObjectURL(e.data);
   recorder=false;
   recordingstream=false;
  });
  recorder.stop();
    } 

// wire up buttons to stop and play audio, and range slider control

play.onclick = function() {
  getData();
  source.start(0);
  play.setAttribute('disabled', 'disabled');
  playbackControl.removeAttribute('disabled');
  loopstartControl.removeAttribute('disabled');
  loopendControl.removeAttribute('disabled');
  startrecording();
  glue(source);

}

stop.onclick = function() {
  source.stop(0);
  play.removeAttribute('disabled');
  playbackControl.setAttribute('disabled', 'disabled');
  loopstartControl.setAttribute('disabled', 'disabled');
  loopendControl.setAttribute('disabled', 'disabled');
  stoprecording();

}


playbackControl.oninput = function() {
  source.playbackRate.value = playbackControl.value;
  playbackValue.innerHTML = playbackControl.value;
}

loopstartControl.oninput = function() {
  source.loopStart = loopstartControl.value;
  loopstartValue.innerHTML = loopstartControl.value;
}

loopendControl.oninput = function() {
  source.loopEnd = loopendControl.value;
  loopendValue.innerHTML = loopendControl.value;
}

Исходный пример decodeAudioData (без моей попытки записи) взят из документации Mozilla здесь: https://mdn.github.io/webaudio-examples/decode-audio-data/ от chrisdavidmills


person Cameron    schedule 22.03.2021    source источник
comment
Не уверен, что происходит, но я взял ваш пример кода и создал с ним эту скрипту. Это работает, как только я заменил ваш precky.mp3 чем-то, что мне доступно. См. jsfiddle.net/rtoy/2wx967qc/4.   -  person Raymond Toy    schedule 23.03.2021
comment
Привет, спасибо, я только что попробовал это в месте Fiddle, которое вы указали. Синусоида, которую вы использовали, воспроизводится, и аудиоэлемент показывает продолжительность после нажатия кнопки остановки, но когда вы затем пытаетесь воспроизвести аудиоэлемент, звука нет. Это то же самое, что я испытал. Однако консоль в Fiddle не показывает ошибок. После моего вчерашнего поста я добавил source.connect(recordingstream); в функции startrecording() в промежутке между recordstream=audioCtx.createMediaStreamDestination(); и рекордер = новый MediaRecorder (recordingstream.stream); Он работает, но показывает те же ошибки.   -  person Cameron    schedule 23.03.2021