Proposed API change

The current API delivers the encoded stream as individual chunks of binary data, delivered every n milliseconds. The proposed new API will instead deliver data using the Streams API[1].

We have already kicked off an initial discussion on public-media-capture.[2]

Removed

void record (optional long? timeslice);

Added

Stream recordToStream(optional StreamBuilder b);

Promise<Blob> recordToBlob();

Sample Code - Record To File

var recorder = new MediaRecorder(input);

var stream = recorder.recordToStream(

    new StreamBuilder(“file.vp9”, FileMode.OpenOrCreate));

Streams API Upsides

Better Data Model

Streams are a more natural model of the resulted encoding data. MediaRecorder encodes a contiguous stream of data into ultimately a single contiguous stream of data. The intermediate use of individual/discrete blob chunks merely is a result of implementation choices leaking out, not a good representation of the data.

Mime type

One of the issues with the current API discussed on public-media-capture was that of blob mime types.[3] Each blob should have a mime type, but it's not entirely clear what type it should be. The mime type of the final encoding result makes only sense for the entire data set, not for individual chunks of data. Representing the data as a stream makes clear there are no chunks that can be independently consumed.

Flow Control

The Flow Control on Stream can be done with existing APIs -- no new events or methods required.

One issue that we identified while looking at the API is that especially for the video use case, there are large data amounts. If the client fails to consume them in a timely manner, we run into resource limits. With Blobs, the only option to handle those is hidden inside the UA. (Note: we want MediaRecorder to deliver a final blob that finishes a stream in a readable manner on failure. That's independent of this, but needs to go into the spec).

With StreamBuilder, that is at least somewhat under the control of the app developer. If there is e.g. a network congestion issue that prevents delivery, the app dev can choose to just accumulate in memory (i.e. for audio apps - memory usage is fairly low), into a ByteArray (no GC pressure), temporarily buffer to disk, stop recording, cut over to a stream with lower fidelity (N.B - mediarecorder needs to provide that), etc.

Quota handling

It falls under whatever quota system that the dev uses - Blobs don't have clear quota affinity or location in the spec. Depending on the UA's choice of storage for blobs, they're either constrained by available memory (which could be surprising since it increases GC pressure for the whole app) or to disk (in which case it is not clear if it goes against any quota API, or if it "just" uses up disk space. Note: What happens to on-disk blobs after a crash, btw?). Using StreamBuilder instead maps clearly to the quota API of whatever storage medium the app developer uses. There are fewer surprises for the app developer.

Simpler API

Default Use Case

The default use case (Recording to files) is now trivial. With blobs, this still requires a bit of code if the app wants to store the result in a particular spot. With StreamBuilder, the user can just pass in a StreamBuilder hooked to a particular file and be done. The file will show up in the desired spot on Stream.onloadend

No optional parameter

No need for the "no timeslice" case any more - if the app dev needs/wants to accumulate the whole data, that's up to the StreamBuilder.(Or use BlobBuilder[4])  And in case she later changes her mind and wants time slicing, there are less changes to the code, since StreamBuilder already is capable of consuming slices only.

Composeable

The resulting stream builders are building blobs that might be usable outside of just MediaRecorder applications. (I.e. a WebSocket streaming StreamBuilder, etc.). It makes for a more composable API.

Modern

Flexible, modern API. Blob is a - for web standards - fairly old API, and has issues associated with it. (See e.g. the discussion around streaming blobs). Streams are already a more modern API. As an added benefit, MediaRecorder will now support Promises whenever Streams support them, without having to change the MediaRecorder spec.

Blob API upsides

Current Spec

It's already in the spec. There's an implementation with more happening. It is unclear how much resistance a large change to the API would generate. Mitigating this: It is fairly easy to write a shim that implements the blob API on top of the streams version of MediaRecorder.

Stable API

Blobs are a stable API, as opposed to Streams which are currently under discussion.

References

[1] Streams API Editors Draft - https://dvcs.w3.org/hg/streams-api/raw-file/tip/Overview.htm

[2] “MediaRecorder and using Streams: - http://lists.w3.org/Archives/Public/public-media-capture/2013Aug/0000.html

[3] “Recording and MIME Types” - http://lists.w3.org/Archives/Public/public-media-capture/2013Jul/0093.html

[4] BlobBuilder interface - http://www.w3.org/TR/file-writer-api/#the-blobbuilder-interface