如何在Safari中为Canvas录制的MP4文件添加静默AAC音频声道
解决方案
你可以通过往Canvas捕获的媒体流中额外注入一条静默音频轨道的方式,实现输出包含AAC音频+H.264视频编码的MP4文件,以下是具体实现:
实现步骤
- 创建AudioContext实例生成静默音频流,注意Safari要求AudioContext必须由用户交互(如点击、触摸事件)触发初始化,否则会被限制音频输出
- 从静默音频流中取出音频轨道,和Canvas捕获流的视频轨道合并为新的MediaStream
- 初始化MediaRecorder时明确指定包含H.264和AAC编码的mimeType,强制Safari启用双编码输出
修改后代码示例
// 注意:以下代码必须在用户交互回调(如点击事件)中执行,避免Safari限制AudioContext const recordedChunks = []; const stream = canvas.captureStream(60); // 新增:创建静默音频流 const audioCtx = new (window.AudioContext || window.webkitAudioContext)(); const destination = audioCtx.createMediaStreamDestination(); // 创建增益节点设为0,生成完全静默的音频 const gainNode = audioCtx.createGain(); gainNode.gain.value = 0; gainNode.connect(destination); const oscillator = audioCtx.createOscillator(); oscillator.connect(gainNode); oscillator.start(); const audioStream = destination.stream; // 合并视频轨道和音频轨道 const combinedStream = new MediaStream([ ...stream.getVideoTracks(), ...audioStream.getAudioTracks() ]); // 指定明确的编码格式,确保Safari识别 mediaRecorder = new MediaRecorder(combinedStream, { mimeType: 'video/mp4; codecs="avc1.4D401E, mp4a.40.2"' }); mediaRecorder.ondataavailable = (e) => recordedChunks.push(e.data); mediaRecorder.onstop = async (e) => { const download = (fileName, url) => { const a = document.createElement("a"); document.body.appendChild(a); a.style = "display: none"; a.href = url; a.download = fileName; a.click(); window.URL.revokeObjectURL(url); }; // download video const videoData = new Blob(recordedChunks, { type: "video/mp4" }); download("1.mp4", URL.createObjectURL(videoData)); // 停止音频节点释放资源 oscillator.stop(); audioCtx.close(); } // start recording mediaRecorder.start(); // do some canvas related operations // ... mediaRecorder.stop();
备用方案
如果上述前端方案在你使用的Safari版本中不生效,可以选择FFmpeg添加静默音频轨道,命令如下:
ffmpeg -i 仅视频的输入.mp4 -f lavfi -i anullsrc=channel_layout=stereo:sample_rate=44100 -c:v copy -c:a aac -shortest 带音频的输出.mp4
该命令会直接复制原有H.264视频流,同时生成AAC编码的静默音频流合并输出,不会损失原视频质量。
内容的提问来源于stack exchange,提问作者H S
相关产品推荐
相关产品推荐

