To upload live audio and video, convert MediaStreamTrack objects into ReadableStreams of unencoded media using MediaStreamTrackProcessor. Then, feed these streams into AudioEncoder and VideoEncoder instances.
Workflow:
- Use
MediaStreamTrackProcessor(track).readable to get a stream of raw frames. - Configure encoders with a specific
codec and tuning parameters (like bitrate, framerate, width, and height). - The
output callback of the encoder receives byte arrays (encoded chunks) which are not in a container (like MP4); your application is responsible for muxing/containerizing these chunks before transmission. - Use a loop or stream reader to continuously call
encoder.encode(frame).
// The tracks are converted to ReadableStreams of unencoded audio and video.
const audio = (new MediaStreamTrackProcessor(audioTrack)).readable;
const video = (new MediaStreamTrackProcessor(videoTrack)).readable;
// Build and configure the encoders.
const audioEncoder = new AudioEncoder({
output: muxAndSend,
error: onEncoderError,
});
const audioPromise = audioEncoder.configure({
codec: 'opus',
tuning: {
bitrate: 60_000,
}
});
const videoEncoder = new VideoEncoder({
output: muxAndSend,
error: onEncoderError,
});
const videoPromise = videoEncoder.configure({
codec : 'vp8',
tuning: {
bitrate: 1_000_000,
framerate: 24,
width: 1024,
height: 768
}
});
try {
await Promise.all([audioPromise, videoPromise]);
} catch (exception) {
// Configuration not supported.
return;
}
// Helper to feed raw media to encoders as fast as possible.
function readAndEncode(reader, encoder) {
reader.read().then((result) => {
if (result.done) return;
encoder.encode(result.value);
readAndEncode(reader, encoder);
});
}
// Feed the encoders data from the track readers.
readAndEncode(audio.getReader(), audioEncoder);
readAndEncode(video.getReader(), videoEncoder);