Gio*_*ino 8 browser audio audio-recording getusermedia mediadevices
使用浏览器Web API,我想设置适合录制音频语音(语音消息)的MediaDevices.getUserMedia 约束属性,例如设置这些参数:
这是我的代码:
const mediaStreamConstraints = {
audio: {
channelCount: 1,
sampleRate: 16000,
sampleSize: 16,
volume: 1
},
video: false
}
navigator.mediaDevices.getUserMedia(mediaStreamConstraints)
.catch( err => serverlog(`ERROR mediaDevices.getUserMedia: ${err}`) )
.then( stream => {
// audio recorded as Blob
// and the binary data are sent via socketio to a nodejs server
// that store blob as a file (e.g. audio/inp/audiofile.webm)
} )
Run Code Online (Sandbox Code Playgroud)
录制的剪辑被抓取并存储(使用MediaRecorderAPI),最终发送到 Nodejs 服务器,其中 blob 被保存为文件并进行处理(该应用程序是一个语音机器人)。
出现问题,WebM 保存的文件没有所需的参数:
$ mediainfo audio/inp/audiofile.webm
General
Complete name : audio/inp/audiofile.webm
Format : WebM
Format version : Version 4 / Version 2
File size : 2.04 KiB
Writing application : Chrome
Writing library : Chrome
IsTruncated : Yes
Audio
ID : 1
Format : Opus
Codec ID : A_OPUS
Channel(s) : 1 channel
Channel positions : Front: C
Sampling rate : 48.0 kHz
Bit depth : 32 bits
Compression mode : Lossy
Language : English
Default : Yes
Forced : No
Run Code Online (Sandbox Code Playgroud)
例如
Sampling rate : 48.0 kHz
Bit depth : 32 bits
Run Code Online (Sandbox Code Playgroud)
但约束会意味着不同的值:
Sampling rate : 16 kHz
Bit depth : 16 bits
Run Code Online (Sandbox Code Playgroud)
而且,重新玩过的 blob 也Audio(audioUrl(blob)).play()不会玩。诡异的。但如果约束条件是这样的,那么一切都有效:
const mediaStreamConstraints = { audio: true }
Run Code Online (Sandbox Code Playgroud)
我检查了浏览器控制台,没有看到任何navigator.mediaDevices.getUserMedia(mediaStreamConstraints)API 调用错误。
顺便说一句,我遵循这里的指导方针:
请注意,我的用户代理是:(Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36我使用的是最新的 Brave 浏览器版本)。
在我看来,浏览器不允许任何音频约束设置:
navigator.mediaDevices.getUserMedia()和new MediaRecorder(...)。这不是最后一个至少是一个错误吗?我的问题是:
有什么办法可以满足要求的采样率/位深度?
或者音频格式是“硬编码”/由浏览器实现决定的?
顺便说一句,音频参数格式的原因是因为我想最小化音频 blob 大小,以最小化浏览器客户端和服务器之间的 websocket 通信中的带宽,优化语音的音频 blob 交换(语音消息)
首先检查您的浏览器的功能:
let stream = await navigator.mediaDevices.getUserMedia({audio: true});
let track = stream.getAudioTracks()[0];
console.log(track.getCapabilities());
Run Code Online (Sandbox Code Playgroud)
演示输出:
autoGainControl: (2) [true, false]
channelCount: {max: 2, min: 1}
deviceId: "default"
echoCancellation: (2) [true, false]
groupId: "1e76386ad54f9ad3548f6f6c14c08e7eff6753f9362d93d8620cc48f546604f5"
latency: {max: 0.01, min: 0.01}
noiseSuppression: (2) [true, false]
sampleRate: {max: 48000, min: 48000}
sampleSize: {max: 16, min: 16}
Run Code Online (Sandbox Code Playgroud)
在实例化 MediaRecorder 之前,尝试在流中的音频媒体轨道上设置音频约束。
类似这样的,未调试:
const constraints = {
audio: {
channelCount: 1,
sampleRate: 16000,
sampleSize: 16,
volume: 1
},
navigator.mediaDevices.getUserMedia({audio:true})
.catch( err => serverlog(`ERROR mediaDevices.getUserMedia: ${err}`) )
.then( stream => {
const audioTracks = stream.getAudioTracks()
if (audioTracks.length !== 1) throw new Error ('too many tracks???')
const audioTrack = audioTracks[0]
audioTrack.applyConstraints (constraints)
.then (()=> {
const mediaRecorder = new MediaRecorder(stream)
/* etc etc etc */
} )
.catch(console.error) /* you might get constraint failure here. */
} )
Run Code Online (Sandbox Code Playgroud)
话虽如此,Opus 音频编解码器在将语音压缩到合理的大小方面做得很好。仅仅因为它是 48kHz x 32 位并不意味着它使用那么多带宽;音频信号被压缩。
并且,请在最新版本的 Google Chrome 和/或 Firefox 上尝试一下。该媒体产品正在积极开发中。