Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Specifying codecs with MediaRecorder

How can I specify the codecs used with the MediaRecorder API? The only option I see is for mimeType which isn't really sufficient. Cramming in the codecs in the mimeType option doesn't seem to work.

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

This results in a WebM stream with Vorbis and VP8:

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)

If I make a MediaStream that only has an audio track (no video), then the MediaRecorder outputs Opus audio in an Ogg container:

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

How can I get Opus audio with VP8 video in a WebM container with the MediaRecorder API?

Firefox v44.0.2

like image 472
Brad Avatar asked Feb 17 '16 19:02

Brad


People also ask

How does the mediarecorder() constructor work?

The MediaRecorder () constructor creates a new MediaRecorder object that will record a specified MediaStream . The object can optionally be configured to record using a specific media container (file type), and, further, can specify the exact codec and codec configuration (s) to use by specifying the codecs parameter .

How to use mediarecorder API to record audio and video?

In that case, we can use the MediaRecorder API to record the media streaming. In this article, we will create a basic Video and Audio Recorder website using pure JavaScript and its MediaRecorder API. A select option to let the users choose what type of media (audio or video with audio) to record. The “Stop Recording” button will stop the recording.

What is mediarecorder object in Java?

MediaRecorder () The MediaRecorder () constructor creates a new MediaRecorder object that will record a specified MediaStream. The object can optionally be configured to record using a specific media container (file type), and, further, can specify the exact codec and codec configuration (s) to use by specifying the codecs parameter.

What file formats are supported by the mediarecorder?

Safari currently supports the MP4 file format with H.264 as video codec and AAC as audio codec. MediaRecorder support can be checked as follows: function supportsRecording ( mimeType ) { if (! window.


2 Answers

How can I get Opus audio with VP8 video in a WebM container with the MediaRecorder API?

Unfortunately this is apparently impossible at this time. In fact it seems not even the mimetype can currently be set, in addition to the audio/video stream codecs. Firefox decides what encoder to used from those that are available, based on the requested streams, and the JavaScript API doesn't offer much say in the matter.

As always, the proof is in the source.

Here is where the encoded is initialized from the mimetype.

Excerpt from 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);
    }

A we can see, except for the 3GPP* mimes, the mimetype passed to CreateEncoded is an empty string NS_LITERAL_STRING("").

This comment does offer hope for the future though:

// At this stage, the API doesn't allow UA to choose the output mimeType format.

Excerpts from dom/media/encoder/MediaEncoder.cpp:

The first case for video with WebM enabled.

  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);
  }

The final case for just audio with OGG enabled.

  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);
  }

Base on this code, I think we can conclude that at this point it's not possible, but it does appear to be on the roadmap.

@jib located the following related Mozilla bugs reports.

  • https://bugzil.la/987568
  • https://bugzil.la/963238
like image 137
Alexander O'Mara Avatar answered Oct 18 '22 03:10

Alexander O'Mara


Check out the Chrome LayoutTests for isTypeSupported(), the mimeType used there should be applicable to the MediaRecorder constructor.

like image 24
miguelao Avatar answered Oct 18 '22 04:10

miguelao