簡體   English   中英

我可以記錄一個的輸出 <audio> 不使用麥克風?

[英]Can I record the output of an <audio> without use of the microphone?

我有一個<audio>元素,我正在改變速度,開始/結束界限和音高。 我想看看是否可以在瀏覽器中錄制我聽到的音頻。 但是我不想只是用麥克風錄音,因為質量較差。

我可以在服務器端做同樣的效果,但我不願意,因為我基本上會用兩種不同的技術復制相同的功能。


為了回應旗幟投票,因為它“不清楚我在問什么”,我會改寫。

我在頁面上播放了<audio>元素。 我有一些javascript操縱播放率,音量等。然后我希望我的瀏覽器錄制音頻, 因為我聽到它 這不是麥克風。 我想創建一個盡可能接近播放的新音頻文件。 如果它是75%,則新文件的容量將為75%。

在支持瀏覽器時,您可以使用MediaElement.captureStream()方法以及MediaRecorder API

但請注意,這些技術仍在積極開發中,並且當前的實現仍然充滿了錯誤。
例如,對於您的情況,如果您在錄制時更改其音量,當前穩定的FF將停止呈現原始媒體音頻...我沒有時間搜索它的錯誤報告,但無論如何,這只是一個您會發現許多錯誤。

 // here we will save all the chunks of our record const chunks = []; // wait for the original media is ready audio.oncanplay = function() { audio.volume = 0.5; // just for your example // FF still does prefix this unstable method var stream = audio.captureStream ? audio.captureStream() : audio.mozCaptureStream(); // create a MediaRecorder from our stream var rec = new MediaRecorder(stream); // every time we've got a bit of data, store it rec.ondataavailable = e => chunks.push(e.data); // once everything is done rec.onstop = e => { audio.pause(); // concatenate our chunks into one file let final = new Blob(chunks); let a = new Audio(URL.createObjectURL(final)); a.controls = true; document.body.append(a); }; rec.start(); // record for 6 seconds setTimeout(() => rec.stop(), 6000); // for demo, change volume at half-time setTimeout(() => audio.volume = 1, 3000); }; // FF will "taint" the stream, even if the media is served with correct CORS... fetch("https://dl.dropboxusercontent.com/s/8c9m92u1euqnkaz/GershwinWhiteman-RhapsodyInBluePart1.mp3").then(resp => resp.blob()).then(b => audio.src = URL.createObjectURL(b)); 
 <audio id="audio" autoplay controls></audio> 

對於舊版瀏覽器,您可以使用WebAudio API的createMediaElementSource方法,通過API傳遞音頻元素媒體。
從那里,您將能夠將原始PCM數據提取到arrayBuffers並保存。

在下面的演示中,我將使用recorder.js庫,它對提取+保存到wav進程有很大幫助。

 audio.oncanplay = function(){ var audioCtx = new AudioContext(); var source = audioCtx.createMediaElementSource(audio); var gainNode = audioCtx.createGain(); gainNode.gain.value = 0.5; source.connect(gainNode); gainNode.connect(audioCtx.destination); var rec = new Recorder(gainNode); rec.record(); setTimeout(function(){ gainNode.gain.value = 1; }, 3000); setTimeout(function(){ rec.stop() audio.pause(); rec.exportWAV(function(blob){ var a = new Audio(URL.createObjectURL(blob)); a.controls = true; document.body.appendChild(a); }); }, 6000); }; 
 <script src="https://rawgit.com/mattdiamond/Recorderjs/master/dist/recorder.js"></script> <audio id="audio" crossOrigin="anonymous" controls src="https://dl.dropboxusercontent.com/s/8c9m92u1euqnkaz/GershwinWhiteman-RhapsodyInBluePart1.mp3" autoplay></audio> 

正如Kaiido在他的回答中提到的, captureStream()是這樣做的一種方式。 但是,Chrome和Firefox尚不完全支持。 MediaRecorder在錄制過程中也不允許更改軌道集,而來自captureStream()的MediaStream可能具有這些(取決於應用程序) - 從而過早地結束錄制。

如果您需要一種支持從媒體元素錄制音頻的方式,則可以使用MediaElementAudioSourceNode ,將其傳遞給MediaStreamAudioDestinationNode ,並將其stream屬性傳遞給MediaRecorder。

以下是您可以在具有現有音頻元素的頁面上使用的示例:

const a = document.getElementsByTagName("audio")[0];
const ac = new AudioContext();
const source = ac.createMediaElementSource(a);

// The media element source stops audio playout of the audio element.
// Hook it up to speakers again.
source.connect(ac.destination);

// Hook up the audio element to a MediaStream.
const dest = ac.createMediaStreamDestination();
source.connect(dest);

// Record 10s of audio with MediaRecorder.
const recorder = new MediaRecorder(dest.stream);
recorder.start();
recorder.ondataavailable = ev => {
  console.info("Finished recording. Got blob:", ev.data);
  a.src = URL.createObjectURL(ev.data);
  a.play();
};
setTimeout(() => recorder.stop(), 10 * 1000);

請注意,如果沒有正確的CORS設置,這兩種方法都不適用於跨源音頻源,因為WebAudio和錄音都可以讓應用程序檢查音頻數據。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM