使用MediaRecorder指定编解码器

Bra*_*rad 6 firefox webrtc web-mediarecorder mediarecorder-api web-audio-api

如何指定与MediaRecorder API一起使用的编解码器?我看到的唯一选择是mimeType,这还不够.填写mimeType选项中的编解码器似乎不起作用.

var mediaRecorder = new MediaRecorder(
    outputMediaStream
  ),
  {
    mimeType: 'video/webm; codecs="opus,vp8"'
  }
);
Run Code Online (Sandbox Code Playgroud)

这导致带有Vorbis和VP8的WebM流:

FFMPEG STDERR: Input #0, matroska,webm, from 'pipe:':
  Metadata:
    encoder         : QTmuxingAppLibWebM-0.0.1
  Duration: N/A, start: 0.000000, bitrate: N/A
    Stream #0:0(eng): Video: vp8, yuv420p, 640x360, SAR 1:1 DAR 16:9, 30 fps, 30 tbr, 1k tbn, 1k tbc (default)
    Stream #0:1(eng): Audio: vorbis, 44100 Hz, stereo, fltp (default)
Run Code Online (Sandbox Code Playgroud)

如果我制作的MediaStream只有一个音轨(没有视频),那么MediaRecorder会在一个Ogg容器中输出Opus音频:

FFMPEG STDERR: Input #0, ogg, from 'pipe:':
  Duration: N/A, start: 0.000000, bitrate: N/A
    Stream #0:0: Audio: opus, 48000 Hz, stereo, fltp
    Metadata:
      ENCODER         : Mozilla44.0.2
Run Code Online (Sandbox Code Playgroud)

如何使用MediaRecorder API在WebM容器中获取带有VP8视频的Opus音频?

Firefox v44.0.2

Ale*_*ara 9

如何使用MediaRecorder API在WebM容器中获取带有VP8视频的Opus音频?

不幸的是,目前这显然是不可能的.事实上,除了音频/视频流编解码器之外,目前似乎还没有设置mimetype.Firefox根据请求的流决定从可用的编码器中使用哪种编码器,并且JavaScript API在此问题上没有多少说法.

与往常一样,证据来自源头.

这是从mimetype初始化编码的地方.

摘录自dom/media/MediaRecorder.cpp:

    // Allocate encoder and bind with union stream.
    // At this stage, the API doesn't allow UA to choose the output mimeType format.

    // Make sure the application has permission to assign AUDIO_3GPP
    if (mRecorder->mMimeType.EqualsLiteral(AUDIO_3GPP) && CheckPermission("audio-capture:3gpp")) {
      mEncoder = MediaEncoder::CreateEncoder(NS_LITERAL_STRING(AUDIO_3GPP),
                                             mRecorder->GetAudioBitrate(),
                                             mRecorder->GetVideoBitrate(),
                                             mRecorder->GetBitrate(),
                                             aTrackTypes);
    } else if (mRecorder->mMimeType.EqualsLiteral(AUDIO_3GPP2) && CheckPermission("audio-capture:3gpp2")) {
      mEncoder = MediaEncoder::CreateEncoder(NS_LITERAL_STRING(AUDIO_3GPP2),
                                             mRecorder->GetAudioBitrate(),
                                             mRecorder->GetVideoBitrate(),
                                             mRecorder->GetBitrate(),
                                             aTrackTypes);
    } else {
      mEncoder = MediaEncoder::CreateEncoder(NS_LITERAL_STRING(""),
                                             mRecorder->GetAudioBitrate(),
                                             mRecorder->GetVideoBitrate(),
                                             mRecorder->GetBitrate(),
                                             aTrackTypes);
    }
Run Code Online (Sandbox Code Playgroud)

我们可以看到,除了3GPP*mimes之外,传递给CreateEncoded它的mimetype 是一个空字符串NS_LITERAL_STRING("").

这条评论确实为未来带来了希望:

// At this stage, the API doesn't allow UA to choose the output mimeType format.
Run Code Online (Sandbox Code Playgroud)

摘录自dom/media/encoder/MediaEncoder.cpp:

启用WebM的视频的第一种情况.

  else if (MediaEncoder::IsWebMEncoderEnabled() &&
          (aMIMEType.EqualsLiteral(VIDEO_WEBM) ||
          (aTrackTypes & ContainerWriter::CREATE_VIDEO_TRACK))) {
    if (aTrackTypes & ContainerWriter::CREATE_AUDIO_TRACK) {
      audioEncoder = new VorbisTrackEncoder();
      NS_ENSURE_TRUE(audioEncoder, nullptr);
    }
    videoEncoder = new VP8TrackEncoder();
    writer = new WebMWriter(aTrackTypes);
    NS_ENSURE_TRUE(writer, nullptr);
    NS_ENSURE_TRUE(videoEncoder, nullptr);
    mimeType = NS_LITERAL_STRING(VIDEO_WEBM);
  }
Run Code Online (Sandbox Code Playgroud)

仅支持启用OGG的音频的最后一种情况.

  else if (MediaDecoder::IsOggEnabled() && MediaDecoder::IsOpusEnabled() &&
           (aMIMEType.EqualsLiteral(AUDIO_OGG) ||
           (aTrackTypes & ContainerWriter::CREATE_AUDIO_TRACK))) {
    writer = new OggWriter();
    audioEncoder = new OpusTrackEncoder();
    NS_ENSURE_TRUE(writer, nullptr);
    NS_ENSURE_TRUE(audioEncoder, nullptr);
    mimeType = NS_LITERAL_STRING(AUDIO_OGG);
  }
Run Code Online (Sandbox Code Playgroud)

基于这段代码,我认为我们可以得出结论,在这一点上它是不可能的,但它似乎确实在路线图上.

@jib找到了以下相关的Mozilla错误报告.

  • 这可能是https://bugzil.la/987568.另外https://bugzil.la/963238会有所帮助. (2认同)

mig*_*lao 3

查看Chrome LayoutTests for isTypeSupported()mimeType那里使用的应该适用于MediaRecorder构造函数。