node-webrtc is a Node.js Native Addon that provides bindings to WebRTC M87
This release of node-webrtc adds non-standard, programmatic audio APIs in the form of RTCAudioSource and RTCAudioSink. These APIs are similar to the previously added RTCVideoSource and RTCVideoSink APIs. With these APIs, you can
onData
method. Then use the RTCAudioSource's createTrack
method to create a local audio MediaStreamTrack.stop
.Because these APIs are non-standard, they are exposed via a nonstandard
property on node-webrtc's exports object. For example,
const { RTCAudioSource, RTCAudioSink } = require('wrtc').nonstandard;
const source = new RTCAudioSource();
const track = source.createTrack();
const sink = new RTCAudioSink(track);
const sampleRate = 8000;
const samples = new Int16Array(sampleRate / 100); // 10 ms of 16-bit mono audio
const data = {
samples,
sampleRate
};
const interval = setInterval(() => {
// Update audioData in some way before sending.
source.onData(data);
});
sink.ondata = data => {
// Do something with the received audio samples.
};
setTimeout(() => {
clearInterval(interval);
track.stop();
sink.stop();
}, 10000);
[constructor]
interface RTCAudioSource {
MediaStreamTrack createTrack();
void onData(RTCAudioData data);
};
dictionary RTCAudioData {
required Int16Array samples;
required unsigned short sampleRate;
octet bitsPerSample = 16;
octet channelCount = 1;
unsigned short numberOfFrames;
};
createTrack
will return a local audio MediaStreamTrack whose source is the RTCAudioSource.onData
with RTCAudioData pushes a new audio samples to every non-stopped local audio MediaStreamTrack created with createTrack
.[constructor(MediaStreamTrack track)]
interface RTCAudioSink {
void stop();
readonly attribute boolean stopped;
attribute EventHandler ondata;
};
stop
.rotation
The RTCVideoFrame raised in RTCVideoSink's "frame" event now includes a property, rotation
, which indicates rotation of the RTCVideoFrame. Possible values are 0, 90, 180, and 270.
handleEvent
EventListener instances now support handleEvent
.
This release of node-webrtc adds non-standard, programmatic video APIs in the form of RTCVideoSource and RTCVideoSink. With these APIs, you can
onFrame
method. Then use RTCVideoSource's createTrack
method to create a local video MediaStreamTrack.stop
.Because these APIs are non-standard, they are exposed via a nonstandard
property on node-webrtc's exports object. For example,
const { RTCVideoSource, RTCVideoSink } = require('wrtc').nonstandard;
const source = new RTCVideoSource();
const track = source.createTrack();
const sink = new RTCVideoSink(track);
const width = 320;
const height = 240;
const data = new Uint8ClampedArray(width * height * 1.5);
const frame = { width, height, data };
const interval = setInterval(() => {
// Update the frame in some way before sending.
source.onFrame(frame);
});
sink.onframe = ({ frame }) => {
// Do something with the received frame.
};
setTimeout(() => {
clearInterval(interval);
track.stop();
sink.stop();
}, 10000);
This release also adds bindings to some libyuv functions for handling I420 frames. These can be useful when converting to and from RGBA.
[constructor(optional RTCVideoSourceInit init)]
interface RTCVideoSource {
readonly attribute boolean isScreencast;
readonly attribute boolean? needsDenoising;
MediaStreamTrack createTrack();
void onFrame(RTCVideoFrame frame);
};
dictionary RTCVideoSourceInit {
boolean isScreencast = false;
boolean needsDenoising;
};
dictionary RTCVideoFrame {
required unsigned long width;
required unsigned long height;
required Uint8ClampedArray data;
};
createTrack
will return a local video MediaStreamTrack whose source is the RTCVideoSource.onFrame
with an RTCVideoFrame pushes a new video frame to every non-stopped local video MediaStreamTrack created with createTrack
.[constructor(MediaStreamTrack track)]
interface RTCVideoSink {
void stop();
readonly attribute boolean stopped;
attribute EventHandler onframe;
};
frame
, of type RTCVideoFrame.stop
.i420ToRgba
and rgbaToI420
These two functions are bindings to libyuv that provide conversions between I420 and RGBA frames. WebRTC expects I420, whereas APIs like the Canvas API expect RGBA, so these functions are useful for converting between. For example,
const { i420ToRgba, rgbaToI420 } = require('wrtc').nonstandard;
const width = 640;
const height = 480;
const i420Data = new Uint8ClampedArray(width * height * 1.5);
const rgbaData = new Uint8ClampedArray(width * height * 4);
const i420Frame = { width, height, data: i420Data };
const rgbaFrame = { width, height, data: rgbaData };
i420ToRgba(i420Frame, rgbaFrame);
rgbaToI420(rgbaFrame, i420Frame);
enabled
property (#475).addTrack
, removeTrack
, etc., with objects that were not instances of MediaStreamTrack, RTCRtpSender, etc., could lead to segfaults. This was because we did not properly validate objects before attempting to unwrap them. (#448)Experimental support for armv7l and arm64. Binaries built for these architectures have been tested with QEMU but not on real devices. Please test them out. If you install node-webrtc directly on an ARM device, node-pre-gyp should pull the correct binaries automatically. Otherwise, you may need to set the TARGET_ARCH
environment variable to "arm" (armv7l) or "arm64". For example,
TARGET_ARCH=arm64 npm install
Set DEBUG=true
to install debug binaries (Linux- and macOS-only). For example,
DEBUG=true npm install
This release adds a number of new features and brings us closer to spec compliance, thanks to the tests at web-platform-tests/wpt.
getUserMedia
This release adds limited getUserMedia
support. You can create audio and video MediaStreamTracks; however, the resulting MediaStreamTracks do not capture any media. You can add these MediaStreamTracks to an RTCPeerConnection; however, no media will be transmitted. You can confirm by checking bytesSent
and bytesReceived
in getStats
.
const { getUserMedia } = require('wrtc');
getUserMedia({
audio: true,
video: true
}).then(stream => {
stream.getTracks().forEach(track => stop());
});
Although we will parse and validate some members of the MediaStreamConstraints and related dictionaries, we do not use their values at this time.
getStats
This release adds limited standards-compliant getStats
support. Previous node-webrtc releases exposed the legacy, callback-based getStats
API. This release preserves that API but adds the Promise-based API. Neither the MediaStreamTrack selector argument nor the RTCRtpSender- and RTCRtpReceiver-level getStats
APIs are implemented at this time.
// Legacy API
pc.getStats(
response => { /* ... */ },
console.error
);
// Standards-compliant API
pc.getStats().then(
report => { /* ... */ },
console.error
);
sdpSemantics
This release adds support for RTCRtpTransceivers and Unified Plan SDP via
sdpSemantics
, andSDP_SEMANTICS
.Construct an RTCPeerConnection with sdpSemantics
set to "unified-plan" or launch your application with SDP_SEMANTICS=unified-plan
to enable RTCRtpTransceiver support; otherwise, "plan-b" is the default.
const { RTCPeerConnection } = require('wrtc');
const pc = new RTCPeerConnection({
sdpSemantics: 'unified-plan' // default is "plan-b"
});
SDP_SEMANTICS=unified-plan node app.js
You can use RTCRtpTransceivers and related APIs when Unified Plan is enabled. This includes the following RTCPeerConnection methods
addTransceiver
getTransceivers
and the following RTCTrackEvent properties
transceiver
The following RTCRtpTransceiver methods are supported
stop
as well as the following RTCRtpTransceiver properties
mid
sender
receiver
stopped
direction
currentDirection
setCodecPreferences
is not yet implemented. When calling addTransceiver
, only the following RTCRtpTransceiverInit dictionary members are supported
direction
streams
const assert = require('assert');
const { MediaStream, RTCPeerConnection, RTCRtpTransceiver } = require('wrtc');
const pc = new RTCPeerConnection({
sdpSemantics: 'unified-plan'
});
const t1 = pc.addTransceiver('audio', {
direction: 'recvonly'
});
const t2 = pc.addTransceiver(t1.receiver.track, {
direction: 'sendonly',
streams: [new MediaStream()]
});
Added limited support for the muted
property (it always returns false
).
addTrack
, will use domexception to construct those DOMExceptions, if installed.addTrack
twice with the same MediaStreamTrack should throw an InvalidAccessError (#442).getTrackById
did not work for video MediaStreamTracks.clone
method did not clone
MediaStreamTracks.readyState
was not updated when stop
was called.