This topic covers the basic functions of the DingRTC SDK, including initialization, joining a channel, local publishing, remote subscription, and leaving a channel.
Prerequisites
You have downloaded and integrated the latest version of the SDK. For more information, see Integrate the SDK for mini programs.
You have obtained the channel authentication token required to join a channel. For more information, see Use Token Authentication.
Key concepts
When you integrate the DingRTC mini program SDK, you will work with the following key concept:
The DingRTCClient class. An instance of this class represents the local client and provides methods to join and leave a channel, and publish and subscribe to audio and video streams.
How it works
Call the createClient() method to create a client instance.
Call the join() method to enter an RTC channel.
Call the publish() method to get a publishing URL, and then start the
live-pushercomponent to begin stream publishing.Subscribe to remote audio and video tracks:
Before joining a channel, listen for the "user-published" event. This event notifies you when remote users publish streams and provides the publisher's information and the track type (audio or video).
Call subscribe('mcu', 'audio') to get the pull URL for the channel's mixed audio, and then start the live-player component to play the audio.
Call subscribe(userId, 'video',false) to get the pull URL for a user's video stream, and then start the live-player component to play that user's video.
Procedure
The implementation in this topic is for reference only. You can adjust it based on your business requirements.
Create a Client instance.
const DingRTC = require('./path/to/dingrtc_mini_program.umd.0.7.0.js'); const client = DingRTC.createClient();Join a channel.
await client.join({ appId: 'your_app_id', // The AppId of your DingRTC project. token: 'your_token', // The channel authentication token. uid: 'user_001', // User ID. Can only contain letters, digits, underscores (_), and hyphens (-). The maximum length is 64 characters. channel: 'channel_001', // Channel ID. Can only contain letters, digits, underscores (_), and hyphens (-). The maximum length is 64 characters. userName: 'Zhang San' // User name. The maximum length is 64 bytes in UTF-8 encoding. });To generate the
your_tokenvalue used in the code, see Use Token Authentication.Information required to join a channel:
Parameter
Type
Description
appId
string
The AppId for your DingRTC project. It must contain only uppercase and lowercase letters, digits, and underscores (_).
channel
string
The channel ID. It must contain only letters, digits, underscores (_), and hyphens (-). The maximum length is 64 characters.
token
string
The channel authentication token.
uid
string
The user ID. It must contain only letters, digits, underscores (_), and hyphens (-). The maximum length is 64 characters.
NoteIf another client joins the channel using the same user ID, it disconnects the first client.
userName
string
The user name. The maximum length is 64 bytes in UTF-8 encoding.
Publish or unpublish local audio and video.
Get the publishing URL for audio and video
// Call the publish method. The SDK returns the publishing configuration. const publishResult = await client.publish(); // publishResult contains pusherUrl, which needs to be bound to the <live-pusher> component. this.setData({ pusherUrl: publishResult.pusherUrl, enableMic: true, enableCamera: true });Use the
live-pushercomponent to publish the stream<live-pusher id="pusher" url="{{pusherUrl}}" mode="RTC" autopush="{{pusherUrl ? true : false}}" enable-mic="{{enableMic}}" enable-camera="{{enableCamera}}" device-position="front" bindstatechange="onPusherStateChangeEvent" bindnetstatus="onPusherNetStatusEvent" binderror="onPushError" />Report the status of the
<live-pusher>component to the SDK// Network status callback onPusherNetStatusEvent(event) { client.reportPusherNetStatus(event.detail); }, // Status change callback onPusherStateChangeEvent(event) { client.reportPusherStateChange(event.detail); }, // Error callback onPushError(event) { console.error('Stream publishing error:', event.detail); client.reportPusherStateChange(event.detail); }Control audio and video capture devices (This is not an SDK feature; control is managed through component properties)
// Mute the microphone this.setData({ enableMic: false }); // Unmute the microphone this.setData({ enableMic: true }); // Disable the camera this.setData({ enableCamera: false }); // Enable the camera this.setData({ enableCamera: true });Unpublish the stream
await client.unpublish(); // Also, clear the publishing URL from the page. this.setData({ pusherUrl: '' });
Subscribe to or unsubscribe from audio and video streams.
Listen for remote user stream publishing events
client.on('user-published', async (user, mediaType, auxiliary) => { console.log(`User ${user.userId} published ${mediaType}`); if (mediaType === 'audio') { // Subscribe to the audio mixing stream (global subscription is only needed once). const subscribeResult = await client.subscribe('mcu', 'audio', false); // Update the audio pull URL. this.setData({ audioRtmpPlayUrl: subscribeResult.rtmpPullUrl }); } else if (mediaType === 'video' && !auxiliary) { // Subscribe to the video stream. const subscribeResult = await client.subscribe(user.userId, 'video', false); // Update the video URL in the user list. this.setData({ userList: this.data.userList.map(u => { if (u.userId === user.userId) { return { ...u, hasVideo: true, rtmpPullUrl: subscribeResult.rtmpPullUrl }; } return u; }) }); } });Audio subscription: The SDK only supports subscribing to the mixed audio stream for the entire channel. To do this, use
'mcu'as the user ID.Video subscription: You must subscribe to each remote user individually to get their RTMP pull URL.
The
auxiliaryparameter indicates whether the stream is an auxiliary stream, such as for screen sharing. It is usuallyfalse.
In WXML, use one hidden
live-playercomponent to play the global audio mixing stream:<live-player wx:if="{{audioRtmpPlayUrl}}" src="{{audioRtmpPlayUrl}}" autoplay="{{audioRtmpPlayUrl ? true : false}}" mode="RTC" style="position: absolute; top:-1rpx; left:-1rpx; width: 1rpx; height: 1rpx;" data-user-id="{{'mcu'}}" min-cache="0.2" max-cache="0.8" bindstatechange="onMcuAudioPlayerStateChange" bindnetstatus="onMcuAudioPlayerNetStatus" binderror="onPlayerError" />In WXML, use a
live-playercomponent for each remote user to play their video stream:<block wx:for="{{userList}}" wx:key="userId"> <live-player wx:if="{{item.hasVideo && item.rtmpPullUrl}}" id="{{item.userId}}" src="{{item.rtmpPullUrl}}" autoplay="true" muted="false" object-fit="cover" style="width:100%;height:100%" data-user-id="{{item.userId}}" min-cache="0.2" max-cache="0.8" bindstatechange="onVideoPlayerStateChange" bindnetstatus="onVideoPlayerNetStatus" binderror="onPlayerError" /> </block>Report the status of the
<live-player>component to the SDK// Audio mixing stream status callback onMcuAudioPlayerNetStatus(event) { const subParam = { uid: 'mcu', mediaType: 'audio', auxiliary: false, }; client.reportPlayerNetStatus(subParam, event.detail); }, onMcuAudioPlayerStateChange(event) { const subParam = { uid: 'mcu', mediaType: 'audio', auxiliary: false, }; client.reportPlayerStateChange(subParam, event.detail); }, // Video status callback onVideoPlayerNetStatus(event) { const userId = event.currentTarget.dataset.userId; const subParam = { uid: userId, mediaType: 'video', auxiliary: false, }; client.reportPlayerNetStatus(subParam, event.detail); }, onVideoPlayerStateChange(event) { const userId = event.currentTarget.dataset.userId; const subParam = { uid: userId, mediaType: 'video', auxiliary: false, }; client.reportPlayerStateChange(subParam, event.detail); }, // Error callback onPlayerError(event) { const userId = event.currentTarget.dataset.userId; console.error(`Player error [${userId}]:`, event.detail); }Unsubscribe from audio and video streams
// Unsubscribe from a video stream await client.unsubscribe(userId, 'video', false); // Update page data to remove the video URL. this.setData({ userList: this.data.userList.map(u => { if (u.userId === userId) { return { ...u, hasVideo: false, rtmpPullUrl: '' }; } return u; }) }); // Unsubscribe from the audio mixing stream (Note: audio only supports the MCU mixing mode). await client.unsubscribe('mcu', 'audio'); // Update page data to indicate that the audio is unsubscribed. this.setData({ hasAudioSubscribed: false });Video: You can unsubscribe from a specific user's stream by passing their
userId.Audio: Since the SDK only supports audio mixing via
'mcu', you must useuserId = 'mcu'to unsubscribe from the mixed audio stream. Unsubscribing from an individual user's audio is not supported.After unsubscribing, promptly clean up related page resources (such as removing the
live-playercomponent and clearing the pull URL) to prevent a memory leak.If a user leaves the channel, the SDK automatically triggers the
user-unpublishedandparticipant-leftevents. You do not need to manually unsubscribe.
Handle reconnection.
// Listen for publishing reconnection. client.on('pub-media-reconnect-started', () => { wx.showToast({ title: 'Reconnecting stream...', icon: 'none' }); }); client.on('pub-media-reconnect-succeeded', (newRtmpUrl) => { wx.showToast({ title: 'Stream reconnected', icon: 'none' }); // You must update the url property of the live-pusher. this.setData({ pusherUrl: newRtmpUrl }); }); client.on('pub-media-reconnect-failed', () => { wx.showModal({ title: 'Stream reconnection failed', content: 'Please check your network connection.', showCancel: false }); }); // Listen for subscription reconnection. client.on('sub-media-reconnect-started', (subParam) => { console.log(`User ${subParam.uid} video is reconnecting...`); }); client.on('sub-media-reconnect-succeeded', (subParam, newRtmpUrl) => { console.log(`User ${subParam.uid} video reconnected`); // You must update the src property of the corresponding live-player. this.updatePlayerUrl(subParam.uid, newRtmpUrl); });Handle errors.
try { await client.join({ appId: 'your_app_id', channel: 'channel_001', token: 'your_token', uid: 'user_001', userName: 'Zhang San' }); } catch (error) { console.error('Failed to join the channel:', error); // Get the error code and error message. const errorCode = error.code; const errorMsg = DingRTC.ErrorCodeAndMsgMap[errorCode] || error.message; console.error(`Error Code: ${errorCode}, Error Message: ${errorMsg}`); // Handle the error based on the error code. switch (errorCode) { case 'INVALID_TOKEN': case 'TOKEN_EXPIRED': // The token is invalid or has expired. Obtain a new one. console.warn('The token is invalid or has expired. Please obtain a new one.'); break; case 'UID_ALREADY_IN_USE': // The UID is already in use. Use a different one. console.warn('This UID is already in use. Please use a different one.'); break; case 'PERMISSION_DENIED': // Permission denied. Guide the user to grant permissions. wx.showModal({ title: 'Permission Prompt', content: 'Camera and microphone permissions are required for video calls', success: (res) => { if (res.confirm) { wx.openSetting(); } } }); break; case 'NETWORK_ERROR': // Network error. Prompt the user to check their network connection. wx.showToast({ title: 'Network connection error', icon: 'none' }); break; default: wx.showToast({ title: 'Operation failed', icon: 'none' }); } }Leave the channel.
async leaveChannel() { try { const leaveResult = await client.leave(); console.log('Successfully left the channel:', leaveResult); // Clear page data. this.setData({ pusherUrl: '', audioRtmpPlayUrl: '', userList: [] }); wx.navigateBack(); } catch (error) { console.error('Failed to leave the channel:', error); } }When leaving the channel, make sure to call the
leave()method to release related resources.When the page unloads, clean up the client instance.
We recommend calling
leave()in theonUnload()lifecycle hook.
Next steps
To quickly establish real-time audio and video communication, download the sample code and run the demo. For more information, see Run the mini program demo.