new MediaRecorder(stream[, options]) 流可以修改吗? [英] new MediaRecorder(stream[, options]) stream can living modify?
问题描述
new MediaRecorder(stream[, options]);
我想记录用户的摄像头和音频
我需要在录音时将 song.mp3 混合到音轨中.
并导出视频文件以通过链接下载.
但是MediaRecorder的第一个参数流可以修改吗?
但是当我使用 recoder.stop()
提示错误:无法在MediaRecorder"上执行stop":MediaRecorder 的状态为inactive".
我的代码:
function getFileBuffer(filepath) {return fetch(filepath, {method: 'GET'}).then(response => response.arrayBuffer())}函数 mp3play() {getFileBuffer('song.mp3').then(buffer => context.decodeAudioData(buffer)).then(缓冲区=> {控制台日志(缓冲区)const 源 = context.createBufferSource()源.缓冲区 = 缓冲区让音量 = context.createGain()音量.增益.值 = 1source.connect(音量)dest = context.createMediaStreamDestination()音量.connect(dest)//volume.connect(context.destination)源.开始(0)const _audioTrack = stream.getAudioTracks();如果(_audioTrack.length > 0){_audioTrack[0].stop();stream.removeTrack(_audioTrack[0]);}////console.log(dest.stream)//console.log(dest.stream.getAudioTracks()[0])//stream.addTrack(dest.stream.getAudioTracks()[0])})}功能开始录音(){记录器 = 新媒体记录器(流,{mimeType: '视频/网络'})recorder.start()stopBtn.removeAttribute('禁用')startBtn.disabled = true}
不,我们仍然无法录制在录制开始后轨道发生变化的 MediaStream,这样做将 stop()
MediaRecorder.这是一个非常相关的问答,更多的是关于录制视频.
但可以做的是创建一种合并 MediaStream.
音频更容易,而且因为您已经在使用 WebAudio API:您需要做的就是创建另一个 MediaStreamDestination 节点,并连接/断开不同的源.
const base = "https://upload.wikimedia.org/wikipedia/en/d/";常量网址 = ["d3/Beach_Boys_-_Good_Vibrations.ogg","dc/Strawberry_Fields_Forever_%28Beatles_song_-_sample%29.ogg"].map( url => base + url );const context = new AudioContext();const button = document.querySelector('button');button.onclick = async() =>{button.disabled = true;上下文.resume();const audiobuffers = await Promise.all( urls.map( fetchAsAudioBuffer ) );button.remove();const streamNode = context.createMediaStreamDestination();const 流 = streamNode.stream;const recorder = new MediaRecorder(stream);常量块 = [];recorder.ondataavailable = evt =>块.push(evt.data);recorder.onstop = evt =>exportAudio(new Blob(chunks));document.getElementById('record-stopper').onclick = evt =>{recorder.stop();current_source.stop( 0 );};让 current_index = 0;让 current_source = null;document.getElementById( 'switcher' ).onclick = switchAudioSource;switchAudioSource();录音机开始();功能 switchAudioSource() {如果(当前来源){current_source.stop( 0 );}current_index = (current_index + 1) % audiobuffers.length;current_source = context.createBufferSource();current_source.buffer = audiobuffers[ current_index ];current_source.loop = true;current_source.connect(streamNode);current_source.connect( context.destination );current_source.start( 0 );}};函数 exportAudio( blob ) {const aud = new Audio( URL.createObjectURL( blob ) );aud.controls = true;document.body.prepend(aud);}异步函数 fetchAsAudioBuffer( url ) {const buf = 等待 fetchAsBuffer( url );返回 context.decodeAudioData( buf );}异步函数 fetchAsBuffer( url ) {const resp = await fetch( url );返回 resp.arrayBuffer();}
button+.recording-controls,音频+.录音控制{显示:无;}
<button>begin</button><div class="recording-controls"><label>录音...</label><button id="switcher">切换音频源</button><button id="record-stopper">停止录制</button>
对于意味着录制 CanvasMediaStreamTrack 并在源上绘制不同视频流的视频,但这样做通常会降低很多质量...
new MediaRecorder(stream[, options]);
I want record the user camera and audio
I need mixing the song.mp3 to the audio track in recording.
and result export a video file to download by link.
But the MediaRecorder first params stream can living modify ?
But When I use recoder.stop()
It tips error: Failed to execute 'stop' on 'MediaRecorder': The MediaRecorder's state is 'inactive'.
My code:
function getFileBuffer(filepath) {
return fetch(filepath, {method: 'GET'}).then(response => response.arrayBuffer())
}
function mp3play() {
getFileBuffer('song.mp3')
.then(buffer => context.decodeAudioData(buffer))
.then(buffer => {
console.log(buffer)
const source = context.createBufferSource()
source.buffer = buffer
let volume = context.createGain()
volume.gain.value = 1
source.connect(volume)
dest = context.createMediaStreamDestination()
volume.connect(dest)
// volume.connect(context.destination)
source.start(0)
const _audioTrack = stream.getAudioTracks();
if (_audioTrack.length > 0) {
_audioTrack[0].stop();
stream.removeTrack(_audioTrack[0]);
}
//
// console.log(dest.stream)
// console.log(dest.stream.getAudioTracks()[0])
// stream.addTrack(dest.stream.getAudioTracks()[0])
})
}
function startRecording() {
recorder = new MediaRecorder(stream, {
mimeType: 'video/webm'
})
recorder.start()
stopBtn.removeAttribute('disabled')
startBtn.disabled = true
}
No we still can't record a MediaStream whose tracks are changed after the recording began, doing so will stop()
the MediaRecorder. Here is a very related Q/A which was more about recording video.
What can be done though is to create a kind of merger MediaStream.
It's way easier with audio, moreover since you are already using the WebAudio API: all you need to do is to create an other MediaStreamDestination node, and connect / disconnect the different sources.
const base = "https://upload.wikimedia.org/wikipedia/en/d/";
const urls = [
"d3/Beach_Boys_-_Good_Vibrations.ogg",
"dc/Strawberry_Fields_Forever_%28Beatles_song_-_sample%29.ogg"
].map( url => base + url );
const context = new AudioContext();
const button = document.querySelector( 'button' );
button.onclick = async () => {
button.disabled = true;
context.resume();
const audiobuffers = await Promise.all( urls.map( fetchAsAudioBuffer ) );
button.remove();
const streamNode = context.createMediaStreamDestination();
const stream = streamNode.stream;
const recorder = new MediaRecorder( stream );
const chunks = [];
recorder.ondataavailable = evt => chunks.push( evt.data );
recorder.onstop = evt => exportAudio( new Blob( chunks ) );
document.getElementById( 'record-stopper' ).onclick = evt => {
recorder.stop();
current_source.stop( 0 );
};
let current_index = 0;
let current_source = null;
document.getElementById( 'switcher' ).onclick = switchAudioSource;
switchAudioSource();
recorder.start();
function switchAudioSource() {
if( current_source ) {
current_source.stop( 0 );
}
current_index = (current_index + 1) % audiobuffers.length;
current_source = context.createBufferSource();
current_source.buffer = audiobuffers[ current_index ];
current_source.loop = true;
current_source.connect( streamNode );
current_source.connect( context.destination );
current_source.start( 0 );
}
};
function exportAudio( blob ) {
const aud = new Audio( URL.createObjectURL( blob ) );
aud.controls = true;
document.body.prepend( aud );
}
async function fetchAsAudioBuffer( url ) {
const buf = await fetchAsBuffer( url );
return context.decodeAudioData( buf );
}
async function fetchAsBuffer( url ) {
const resp = await fetch( url );
return resp.arrayBuffer();
}
button+.recording-controls,
audio+.recording-controls {
display: none;
}
<button>begin</button>
<div class="recording-controls">
<label>Recording...</label>
<button id="switcher">Switch Audio Sources</button>
<button id="record-stopper">Stop Recording</button>
</div>
For video that would imply recording a CanvasMediaStreamTrack and drawing the different video streams on the source <canvas>
, but we generally loose a lot of quality doing so...
这篇关于new MediaRecorder(stream[, options]) 流可以修改吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!