TRTC Web SDK v4 → v5 Migration Skill
Overview
This skill automates the migration of TRTC Web SDK code from v4 (trtc-js-sdk) to v5 (trtc-sdk-v5). It analyzes the user's existing v4 codebase, identifies all v4 API patterns, and performs a systematic, safe migration following the official migration guide.
Architecture Change Summary
- v4:
Client + Streamseparated model —TRTC.createClient()for signaling,TRTC.createStream()for media. - v5: Unified
TRTCinstance —TRTC.create()single instance handles everything.
Workflow
CRITICAL: Follow these steps IN ORDER. Do NOT skip steps.
Step 1: Scan — Discover v4 Code
Search the user's codebase to find all files containing v4 SDK patterns.
Search for these v4 markers (use search_content or codebase_search):
TRTC.createClient
TRTC.createStream
trtc-js-sdk
client.join
client.leave
client.publish
client.unpublish
client.subscribe
client.unsubscribe
stream.initialize
stream.play
stream.stop
stream.close
stream.muteAudio
stream.unmuteAudio
stream.muteVideo
stream.unmuteVideo
stream.switchDevice
stream.setVideoProfile
stream.setAudioProfile
client.switchRole
client.enableAudioVolumeEvaluation
client.enableSmallStream
client.setSmallStreamProfile
client.setRemoteVideoStreamType
client.getTransportStats
client.getLocalAudioStats
client.getLocalVideoStats
client.getRemoteAudioStats
client.getRemoteVideoStats
client.sendSEIMessage
client.startPublishCDNStream
client.stopPublishCDNStream
client.on('stream-added
client.on('stream-subscribed
client.on('stream-removed
client.on('stream-updated
client.on('peer-join
client.on('peer-leave
client.on('mute-audio
client.on('unmute-audio
client.on('mute-video
client.on('unmute-video
client.on('client-banned
client.on('network-quality
client.on('connection-state-changed
client.on('error
client.on('audio-volume
client.on('player-state-changed
TRTC.getDevices
TRTC.getCameras
TRTC.getMicrophones
TRTC.getSpeakers
Also inspect createClient() call sites for these v4-only params (they relocate in v5 and are easy to drop):
streamId— CDN relay push stream ID → v5enterRoom({ streamId })userDefineRecordId— cloud recording ID → v5TRTC.create({ userDefineRecordId })pureAudioPushMode,bussinessInfo— internal params, ask user whether still needed
Output a summary listing:
- All files containing v4 code
- For each file: which v4 APIs/events are used
- The overall scope of migration (number of files, complexity estimate)
Step 2: Analyze — Build Migration Plan
Read the reference file at {SKILL_DIR}/references/migration-guide.md for the complete API and event mapping tables.
For each file found in Step 1, create a migration plan:
- Package change:
trtc-js-sdk→trtc-sdk-v5 - Instance creation:
TRTC.createClient()+TRTC.createStream()→TRTC.create() - createClient params relocation:
streamId(CDN relay stream ID) →enterRoom({ streamId });userDefineRecordId(cloud recording) →TRTC.create({ userDefineRecordId }) - Room operations:
client.join()→trtc.enterRoom(),client.leave()→trtc.exitRoom() - Local media:
stream.initialize()+stream.play()+client.publish()→trtc.startLocalVideo()/trtc.startLocalAudio() - Remote media:
client.on('stream-added')+subscribe+stream.play()→trtc.on(TRTC.EVENT.REMOTE_VIDEO_AVAILABLE)+startRemoteVideo() - Screen sharing:
createStream({screen:true})+client.publish(shareStream, {isAuxiliary:true})→trtc.startScreenShare() - Events: Map all v4 events to v5 events (see reference)
- Device APIs:
TRTC.getCameras()→TRTC.getCameraList(), etc. - Statistics:
client.getXxxStats()polling →TRTC.EVENT.STATISTICSevent - CDN publishing:
client.startPublishCDNStream()/stopPublishCDNStream()(manual relay) → CDNStreaming plugin - Other: Small stream, SEI messages, volume detection, role switching, etc.
Step 3: Confirm — Present Plan to User
Present the migration plan to the user with:
- List of files to modify
- Summary of changes per file
- Any breaking changes or behavioral differences to be aware of:
autoReceiveVideodefaults tofalsesince v5.6.0- Audio is auto-subscribed by default in v5
- Statistics are event-driven, not polling-based
modeparam renamed toscene- Auth params (
sdkAppId,userId,userSig) moved from constructor toenterRoom streamId(CDN relay stream ID) moved fromcreateClient()toenterRoom()— silently dropped if left increate()
Wait for user confirmation before proceeding to Step 4.
Step 4: Migrate — Apply Changes
Apply changes file by file using replace_in_file. For each file:
4.1 Update Import
// v4 (FIND)
import TRTC from 'trtc-js-sdk';
// v5 (REPLACE)
import TRTC from 'trtc-sdk-v5';
4.2 Replace Environment Detection
// v4 (FIND)
TRTC.checkSystemRequirements().then((checkResult) => {
if (!checkResult.result) {
// ...
}
});
// v5 (REPLACE)
TRTC.isSupported().then((checkResult) => {
if (!checkResult.result) {
// ...
}
});
Note: The return result structure is the same — both return
{ result: boolean, detail: { isBrowserSupported, isWebRTCSupported, ... } }. v5'sdetailaddsisWebCodecsSupported,isScreenShareSupported,isSmallStreamSupportedfields.
4.3 Replace Instance Creation
// v4 (FIND patterns like)
const client = TRTC.createClient({ sdkAppId, userId, userSig, mode: 'rtc' });
const localStream = TRTC.createStream({ userId, audio: true, video: true });
// v5 (REPLACE with)
const trtc = TRTC.create();
Note: Save the
sdkAppId,userId,userSig, andmodevalues — they will be needed inenterRoom. Also relocate thesecreateClient()params (they are NOT accepted byTRTC.create()and will be silently dropped):
streamId(CDN relay push stream ID) → pass inenterRoom({ streamId })userDefineRecordId(cloud recording) → pass inTRTC.create({ userDefineRecordId })
4.4 Replace Room Operations
// v4
const client = TRTC.createClient({ sdkAppId, userId, userSig, mode: 'rtc', streamId: 'your_stream_id' });
await client.join({ roomId: 1234 });
await client.leave();
// v5 — note: sdkAppId/userId/userSig/scene (and streamId) move here
await trtc.enterRoom({ sdkAppId, userId, userSig, roomId: 1234, scene: 'rtc', streamId: 'your_stream_id' });
await trtc.exitRoom();
4.5 Replace Local Media
// v4 (FIND the pattern of initialize → play → publish)
await localStream.initialize();
localStream.play('local-video-container');
await client.publish(localStream);
// v5 (REPLACE with)
await trtc.startLocalVideo({ view: 'local-video-container' });
await trtc.startLocalAudio();
// v4 cleanup
client.unpublish(localStream);
localStream.close();
// v5 cleanup
await trtc.stopLocalVideo();
await trtc.stopLocalAudio();
4.6 Replace Remote Stream Handling
// v4 (FIND the stream-added → subscribe → stream-subscribed → play pattern)
client.on('stream-added', (event) => {
client.subscribe(event.stream);
});
client.on('stream-subscribed', (event) => {
event.stream.play('remote-container');
});
client.on('stream-removed', (event) => {
event.stream.stop();
});
// v5 (REPLACE with)
trtc.on(TRTC.EVENT.REMOTE_VIDEO_AVAILABLE, ({ userId, streamType }) => {
trtc.startRemoteVideo({ userId, streamType, view: `remote-video-${userId}` });
});
trtc.on(TRTC.EVENT.REMOTE_VIDEO_UNAVAILABLE, ({ userId, streamType }) => {
// Video playback automatically stopped
});
4.7 Replace Event Listeners
Use the event mapping from the reference file. Key mappings:
| v4 Event | v5 Event |
|---|---|
'stream-added' |
TRTC.EVENT.REMOTE_VIDEO_AVAILABLE / TRTC.EVENT.REMOTE_AUDIO_AVAILABLE |
'stream-subscribed' |
(removed — handled internally by startRemoteVideo) |
'stream-removed' |
TRTC.EVENT.REMOTE_VIDEO_UNAVAILABLE / TRTC.EVENT.REMOTE_AUDIO_UNAVAILABLE |
'peer-join' |
TRTC.EVENT.REMOTE_USER_ENTER |
'peer-leave' |
TRTC.EVENT.REMOTE_USER_EXIT |
'mute-audio' |
TRTC.EVENT.REMOTE_AUDIO_UNAVAILABLE |
'unmute-audio' |
TRTC.EVENT.REMOTE_AUDIO_AVAILABLE |
'mute-video' |
TRTC.EVENT.REMOTE_VIDEO_UNAVAILABLE |
'unmute-video' |
TRTC.EVENT.REMOTE_VIDEO_AVAILABLE |
'client-banned' |
TRTC.EVENT.KICKED_OUT |
'network-quality' |
TRTC.EVENT.NETWORK_QUALITY |
'connection-state-changed' |
TRTC.EVENT.CONNECTION_STATE_CHANGED |
'error' |
TRTC.EVENT.ERROR |
'audio-volume' |
TRTC.EVENT.AUDIO_VOLUME |
'player-state-changed' |
TRTC.EVENT.AUDIO_PLAY_STATE_CHANGED / TRTC.EVENT.VIDEO_PLAY_STATE_CHANGED |
4.8 Replace Screen Sharing
// v4
const shareStream = TRTC.createStream({ userId, audio: false, screen: true });
await shareStream.initialize();
await client.publish(shareStream, { isAuxiliary: true });
// v5
await trtc.startScreenShare();
4.9 Replace Device APIs
// v4
TRTC.getDevices() → // removed, use individual list APIs
TRTC.getCameras() → TRTC.getCameraList()
TRTC.getMicrophones() → TRTC.getMicrophoneList()
TRTC.getSpeakers() → TRTC.getSpeakerList()
// v4 device switch
localStream.switchDevice('video', cameraId) → trtc.updateLocalVideo({ option: { cameraId } })
localStream.switchDevice('audio', micId) → trtc.updateLocalAudio({ option: { microphoneId: micId } })
4.10 Replace Statistics
// v4 (FIND polling pattern)
const transportStats = await client.getTransportStats();
const localAudioStats = await client.getLocalAudioStats();
// ...
// v5 (REPLACE with event listener)
trtc.on(TRTC.EVENT.STATISTICS, (event) => {
const { rtt, upLoss, downLoss, localStatistics, remoteStatistics } = event;
// Process statistics...
});
4.11 Replace Other APIs
// Mute/unmute
stream.muteAudio() → trtc.updateLocalAudio({ mute: true })
stream.unmuteAudio() → trtc.updateLocalAudio({ mute: false })
stream.muteVideo() → trtc.updateLocalVideo({ mute: true })
stream.unmuteVideo() → trtc.updateLocalVideo({ mute: false })
// Video/Audio profile
stream.setVideoProfile('480p') → trtc.updateLocalVideo({ option: { profile: '480p' } })
stream.setAudioProfile('standard') → trtc.updateLocalAudio({ option: { profile: 'standard' } })
// Small stream
client.enableSmallStream() + client.setSmallStreamProfile({...})
→ trtc.updateLocalVideo({ option: { small: { width, height, bitrate, frameRate } } })
client.setRemoteVideoStreamType(remoteStream, 'small')
→ trtc.updateRemoteVideo({ userId, streamType: TRTC.TYPE.STREAM_TYPE_MAIN, option: { small: true } })
// Role switch
client.switchRole('anchor') → trtc.switchRole(TRTC.TYPE.ROLE_ANCHOR)
client.switchRole('audience') → trtc.switchRole(TRTC.TYPE.ROLE_AUDIENCE)
// SEI message
client.sendSEIMessage(buffer) → trtc.sendSEIMessage(buffer)
// Volume evaluation
client.enableAudioVolumeEvaluation(200) → trtc.enableAudioVolumeEvaluation(200)
// Destroy
client.destroy() → trtc.destroy()
Step 5: Update package.json
// FIND in package.json dependencies
"trtc-js-sdk": "x.x.x"
// REPLACE with
"trtc-sdk-v5": "latest"
Step 6: Verify — Post-Migration Check
After all changes are applied:
- Re-scan for any remaining v4 patterns (repeat Step 1 search terms)
- Check linter errors using
read_lintson modified files - Report to user:
- Files modified
- Remaining issues (if any)
- Behavioral changes to test manually:
- Remote video requires explicit
startRemoteVideo()call - Remote audio auto-plays by default
- Statistics now via event listener instead of polling
- Screen share simplified to single API call
- Remote video requires explicit
Important Notes
Variable Naming Convention
- v4 uses
clientandlocalStream/remoteStreamas variable names - v5 uses
trtcas the unified variable name - When migrating, rename
client→trtcthroughout the affected scope - Remove all
localStream/remoteStream/shareStreamvariables as they are no longer needed
Handling Complex Patterns
- If v4 code uses multiple clients (e.g., separate client for screen sharing in pre-v4.15), consolidate into a single
trtcinstance in v5 - If v4 code manages stream lifecycle manually (create → initialize → play → publish → unpublish → close), replace with the simplified v5 API calls
- If v4 code uses custom audio/video sources via
createStream({ audioSource, videoSource }), migrate totrtc.startLocalVideo({ option: { videoTrack } })/trtc.startLocalAudio({ option: { audioTrack } })
Plugin Migration
If v4 code uses features that are now plugins in v5 (beauty, AI denoiser, watermark, etc.), guide the user on the new plugin system:
import { Beauty } from 'trtc-sdk-v5/plugins/beauty';
const trtc = TRTC.create({ plugins: [new Beauty()] });
await trtc.startPlugin('Beauty', { beauty: 0.5 });
CDN Publishing (Relay Push)
Two distinct v4 mechanisms — do not mix them up:
- 指定流旁路(auto relay) —
streamIdincreateClient(), requires the console "启用旁路推流" switch. Migrate to thestreamIdparam ofenterRoom()(see 4.4). - 手动旁路(manual relay) —
client.startPublishCDNStream({ streamId, streamType, appId, bizId, url })/client.stopPublishCDNStream(). Migrate to the CDNStreaming plugin:
import { CDNStreaming, PublishMode } from 'trtc-sdk-v5/plugins/cdn-streaming';
const trtc = TRTC.create({ plugins: [CDNStreaming] });
// push main (camera) stream to Tencent Cloud CDN with a custom streamId
await trtc.startPlugin('CDNStreaming', {
target: { publishMode: PublishMode.PublishMainStreamToCDN, streamId: 'your_stream_id' }
});
// push to a third-party CDN
await trtc.startPlugin('CDNStreaming', {
target: { publishMode: PublishMode.PublishMainStreamToCDN, streamId: 'your_stream_id', appId, bizId, url }
});
await trtc.stopPlugin('CDNStreaming', { target: { publishMode: PublishMode.PublishMainStreamToCDN } });
Resources
references/
Contains migration-guide.md — the complete API mapping table, event mapping table, and migration reference extracted from the official TRTC documentation. Always read this file during Step 2 for the authoritative mapping data.