Я получаю сообщение об ошибке при попытке сохранить синусоидальный звук в виде файла .wav - PullRequest
1 голос
/ 23 февраля 2020

Здесь я пытаюсь воспроизвести и записать простую синусоидальную волну на несколько секунд и сохранить ее в виде файла .wav, когда запись остановлена. Но я получаю эту ошибку, и WAV-файл пуст. enter image description here

Вот мой полный код.

ПОЛНЫЙ КОД:

<button onclick="play();">PLAY</button>
<button onclick="r.stop();">STOP</button>

<ul id="recordingslist"></ul>

<script type="text/javascript">
const context = new AudioContext();
const stream = context.createMediaStreamDestination();
let o = null,
    g = null,
    r = null;
function play(){
    o = context.createOscillator();
    g = context.createGain();
    r = new MediaRecorder(stream.stream);
    o.type = "sine";
    o.connect(g);
    o.connect(context.destination);
    o.start();
    r.start();
    r.ondataavailable = function(e) {
        var url = window.URL.createObjectURL(e.data);
        var li = document.createElement('li');
        var au = document.createElement('audio');
        var hf = document.createElement('a');
        au.controls = true;
        au.src = url;
        hf.href = url;
        hf.download = new Date().toISOString() + '.wav';
        hf.innerHTML = hf.download;
        li.appendChild(au);
        li.appendChild(hf);
        document.getElementById('recordingslist').appendChild(li);
        o.stop();
    };
}
</script>

1 Ответ

0 голосов
/ 25 февраля 2020

Несколько вещей здесь.


Относительно части MediaRecorder, событие dataavailable может сработать в любое время, когда браузер сочтет это необходимым, оно может сработать даже без данных вообще. ,

Если вы хотите записать фиксированный промежуток времени, прослушайте событие stop , чтобы создать ссылку для скачивания, и используйте dataavailable one только для pu sh порции данных, которые браузер будет выводить в течение этого времени:


Что касается части AudioContext, представьте себе соединение ссылки как [гитара - педаль (ы) - предусилитель - усилитель] настроить. Каждый connect прокладывает новый провод между двумя узлами.
В вашей настройке вы создали gainNode и подключили к нему свой генератор, теперь вам нужно подключить gainNode (g) к MediaStreamDestinationNode (stream) если хочешь записать. В противном случае ничто не будет передано в устройство записи, так как узел stream-dest не будет подключен ни к чему.

const context = new AudioContext();
const stream = context.createMediaStreamDestination();
    
document.getElementById('btn').onclick = play;

function play(){
  const o = context.createOscillator();
  const g = context.createGain();
  const r = new MediaRecorder(stream.stream);
  o.type = "sine";
  g.gain.value = 0.5;
  o.connect(g);
  // you want to connect the gainNode to the stream-dest
  g.connect(stream);
  // and to the context's dest (speakers)
  g.connect(context.destination);
  o.start(0);
  // we need an Array to store all the chunks
  const chunks = [];
  // in datavailable we only push the new chunks
  r.ondataavailable = function(e) {
    chunks.push(e.data);
  };
  // we wait until the recoder has been stopped to build the final media
  r.onstop = function(e) {
    // concatenate all the chunks in a single Blob
    const blob = new Blob(chunks);
    const url = window.URL.createObjectURL(blob);
    const li = document.createElement('li');
    const au = document.createElement('audio');
    const hf = document.createElement('a');
    au.controls = true;
    au.src = url;
    hf.href = url;
    // setting the filename's extension won't make it a wav file
    // what you have here is an ogg-vorbis audio file.
    hf.download = new Date().toISOString() + '.oga';
    hf.innerHTML = hf.download;
    li.appendChild(au);
    li.appendChild(hf);
    document.getElementById('recordingslist').appendChild(li);
    o.stop();
  };
  r.start();
  // stop the recording in 3s
  setTimeout(() => { r.stop(); }, 3000);
}
<button id="btn">start</button>
<ul id="recordingslist"></ul>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...