please select
RTC Engine
  • Overview
  • Web
    • Run Sample Demo
    • Integration
    • Basic Features
      • Screen Sharing
      • Live Streaming
      • Media Device
      • Audio Volume
      • Set Encoding Profile
      • Detect Network Quality
      • Detect Capabilities
    • Advance Features
      • Enable AI Denoiser
      • Enable Audio Mixer
      • Enable Watermark
      • Enable Virtual Background
      • Enable Beauty and Effects
      • Data Messages
      • Custom Capturing and Rendering
    • API List
    • Released Notes
    • Supported Platforms
    • Web FAQs
      • Optimize Multi-Person Video Calls
      • Handle Autoplay Restriction
      • Handle Firewall Restriction
      • Others
  • Android
    • Run Sample Code
    • Integration
    • Basic Features
      • Sensing Network Quality
      • Enabling Screen Sharing
      • Setting Video Quality
      • Rotating Videos
    • Advanced Features
      • Testing Newwork Quality
      • Custom Capturing and Rendering
      • Custom Audio Capturing and Playback
    • Client APIs
      • Overview
      • TRTCCloud
      • TRTCStatistics
      • TRTCCloudListener
      • TXAudioEffectManager
      • TXBeautyManager
      • TXDeviceManager
      • Type Definition
      • Deprecated Interface
      • Error Codes
    • Solution
      • Real-Time Chorus (TUIKaraoke)
        • Quick Integration
        • Implementation Steps
        • Song Synchronization
        • Lyric Synchronization
        • Vocal Synchronization
        • Mixing Stream Solution
        • TRTCKaraoke APIs
        • FAQs
    • Release Notes
  • iOS
    • Run Sample Code
    • Integration
    • Basic Features
      • Sensing Network Quality
      • Enabling Screen Sharing
      • Setting Video Quality
      • Rotating Videos
    • Advanced Features
      • Testing Network Quality
      • Custom Capturing and Rendering
      • Custom Audio Capturing and Playback
    • Client APIs
      • Overview
      • TRTCCloud
      • TRTCCloudDelegate
      • TRTCStatistics
      • TXAudioEffectManager
      • TXBeautyManager
      • TXDeviceManager
      • Type Definition
      • Deprecated Interface
      • ErrorCode
    • Solution
      • Quick Integration
      • Implementation Steps
      • Song Synchronization
      • Lyric Synchronization
      • Vocal Synchronization
      • Mixing Stream Solution
      • TRTCKaraoke APIs
      • FAQs
    • Release Notes
  • macOS
    • Run Sample Code
    • Integration
    • Basic Features
      • Sensing Network Quality
      • Enabling Screen Sharing
      • Sharing Computer Audio
      • Setting Video Quality
      • Rotating Videos
    • Advanced Features
      • Testing Hardware Devices
      • Testing Network Quality
      • Custom Capturing and Rendering
      • Custom Audio Capturing and Playback
    • Client APIs
      • Overview
      • TRTCCloud
      • TRTCCloudDelegate
      • TRTCStatistics
      • TXAudioEffectManager
      • TXBeautyManager
      • TXDeviceManager
      • Type Definition
      • Deprecated Interface
      • ErrorCode
      • Release Notes
    • Release Notes
  • Windows
    • Run Sample Code
    • Integration
    • Basic Features
      • Sensing Network Quality
      • Enabling Screen Sharing
      • Setting Video Quality
      • Rotating Videos
    • Advanced Features
      • Testing Hardware Devices
      • Testing Network Quality
      • Custom Capturing and Rendering
      • Custom Audio Capturing and Playback
    • Client APIs
      • Overview
      • ITRTCCloud
      • ITRTCStatistics
      • TRTCCloudCallback
      • ITXAudioEffectManager
      • ITXDeviceManager
      • Type Definition
      • Deprecated Interface
      • Error Codes
    • Release Notes
  • Electron
    • Integration
      • 1.API Examples
      • 2.Importing the SDK
      • 3.Entering a Room
      • 4.Subscribing to Audio/Video Streams
      • 5.Publish Audio/Video Streams
      • 6.Exiting a Room
      • 7.Sensing Network Quality
      • 8.Enabling Screen Sharing
      • 9.Sharing Computer Audio
      • 10.Setting Video Quality
      • 11.Rotating Videos
    • Client APIs
      • Overview
      • Error Codes
  • Flutter
    • Integration
      • 1.API Examples
      • 2.Importing the SDK
      • 3.Entering a Room
      • 4.Subscribing to Audio/Video Streams
      • 5.Publish Audio/Video Streams
      • 6.Exiting a Room
      • 7.Sensing Network Quality
      • 8.Enabling Screen Sharing
      • 9.Sharing Computer Audio
      • 10.Setting Video Quality
      • 11.Rotating Videos
    • Client APIs
      • Overview
      • Error Codes
  • Unity
    • Integration
      • 1.API Examples
      • 2Importing the SDK
    • Client APIs
      • Overview
      • Error Codes
  • Qt
    • Integration
      • 1.Importing the SDK
  • Overview
    • Overview
  • Concepts
  • Features
  • Performance Statistics
  • Pricing
    • Free Minutes
    • RTC-Engine Monthly Packages
    • Billing Explanation for Subscription Package Duration
    • Pay-as-you-go
      • Billing of Audio and Video Duration
      • Billing of On-Cloud Recording and Recording Delivery
      • Billing of MixTranscoding and Relay to CDN
  • FAQs
    • FAQs for Beginners
    • Migration Guide
      • Twilio Video to Tencent RTC
      • Billing
      • Features
      • UserSig
      • Firewall Restrictions
      • How to Downsize Installation Package
      • TRTCCalling for Web
      • Audio and Video Quality
      • Others
RTC Engine

Song Synchronization

Real-time synchronization of song progress is required in the real-time solution to avoid increasing end-to-end delay due to song errors after the start of the performance. Synchronizing the song requires using NTP time. The local clocks of different devices are not consistent and there is a certain error, so Tencent Cloud's self-developed NTP service needs to be introduced. At the same time, users who join the chorus midway also need to synchronize the song progress, and only after synchronizing the progress can they participate in the chorus.

Implementation process

The method of synchronizing songs is that the main singer user agrees to start playing the song at a future point in time (such as N seconds after delay), and other users participate in the chorus. The time of each end is based on NTP time, which will start synchronizing after the TRTC SDK is initialized.




The specific process is as follows:
1. Each end performs NTP time calibration, updates and obtains the latest NTP time T to the TRTC cloud.
2. The main singer end sends a chorus signal (custom message) to agree on the start time T2 of the chorus.
3. Preload the song locally based on T2 and play it at a scheduled time.
4. Other chorus users execute step 3 after receiving the chorus signal.
5. During the process, the local song playback progress is verified, and seek calibration is performed when the difference between TE and TC exceeds 50ms.
Note
The 50ms error here is a typical value, which can be adjusted appropriately according to the business tolerance. It is recommended to fluctuate around 50ms.

Timing diagram






The song synchronization timing can mainly be divided into three parts: NTP time calibration, sending and receiving chorus signals, and correcting the song playback progress. The following will provide specific code implementation for these three parts.

Key code implementation

1. NTP calibration time service

// Call the NTP time synchronization interface when entering the room.
[TXLiveBase updateNetworkTime];

// In the TXLiveBaseDelegate callback, determine whether the time synchronization is successful.
- (void)onUpdateNetworkTime:(int)errCode message:(NSString *)errMsg {
// errCode 0: 0: Time synchronization is successful and the deviation is within 30ms;
// 1: Time synchronization is successful, but the deviation may be over 30ms;
// -1: Time synchronization failed.
if (errCode == 0) {
// Call TXLiveBase's getNetworkTimestamp to obtain the NTP timestamp.
NSInteger ntpTime = [TXLiveBase getNetworkTimestamp];
} else {
// Call updateNetworkTime again to initiate a time synchronization.
[TXLiveBase updateNetworkTime];
}
}

2. Sending chorus signals on the main singer end

NSDictionary *json = @{
@"cmd": @"startChorus",
// Scheduled time for a tutti.
@"startPlayMusicTS": @(startTs),
@"musicId": @"musicId",
@"musicDuration": @(musicDuration),
};
NSString *jsonString = [self jsonStringFrom:json];
[trtcCloud sendCustomMessage:jsonString reliable:NO];
Note
It is recommended that the main singer send chorus signal messages to the room at a fixed time frequency in a loop, so that chorus users can join in midway;
The reason for not using SEI messages to send chorus signals is that the SEI information will be inserted into the video frame, causing a lot of invalid information to be carried in the video stream pulled by the audience side.

3. Receiving chorus signals on the chorus end

- (void)onRecvCustomCmdMsgUserId:(NSString *)userId cmdID:(NSInteger)cmdId seq:(UInt32)seq message:(NSData *)message {

NSString *msg = [[NSString alloc] initWithData:message encoding:NSUTF8StringEncoding];
NSError *error;
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:[msg dataUsingEncoding:NSUTF8StringEncoding]
options:NSJSONReadingMutableContainers
error:&error];

NSObject *cmdObj = [json objectForKey:@"cmd"];

NSInteger musicDuration = [[json objectForKey:@"musicDuration"] integerValue];

NSString *cmd = (NSString *)cmdObj;

// tutti command
if ([cmd isEqualToString:@"startChorus"]) {
// tutti start time
NSObject *startPlayMusicTsObj = [json objectForKey:@"startPlayMusicTS"];
NSString *musicId = [json objectForKey:@"musicId"];

NSInteger startPlayMusicTs = ((NSNumber *)startPlayMusicTsObj).longLongValue;
// The difference between the scheduled tutti time and the current time.
NSInteger startDelayMS = labs(startPlayMusicTs - [TXLiveBase getNetworkTimestamp]);
// Start preloading, and jump the song progress according to the difference
// between the scheduled duet time and the current NTP time.
NSDictionary *jsonDict = @{
@"api": @"preloadMusic",
@"params": @{
@"musicId": @(musicId),
@"path": path,
@"startTimeMS": @(startDelayMS),
}
};
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:jsonDict options:0 error:NULL];
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
[subCloud callExperimentalAPI:jsonString];

// play music
TXAudioMusicParam *param = [[TXAudioMusicParam alloc] init];
param.ID = musicId;
param.path = url;
param.loopCount = 0;
param.publish = NO;

[[subCloud getAudioEffectManager] startPlayMusic:param onStart:^(NSInteger errCode) {
// star play callback
} onProgress:^(NSInteger progressMs, NSInteger durationMs) {
// lyric progress callback
} onComplete:^(NSInteger errCode) {
// play completely callback
}];

}
}
Note
After the chorus end receives the first startChorus signal, the status should be changed from "not singing" to "singing", and no longer respond to the startChorus signal to avoid restarting the BGM playback.

4. Song playback progress correction

self.startPlayChorusMusicTs; // The originally scheduled tutti time.
// Current playback progress
NSInteger currentProgress = [[self audioEffecManager] getMusicCurrentPosInMS:self.currentPlayMusicID];
// The ideal playback time progress of the current song.
NSInteger estimatedProgress = [TXLiveBase getNetworkTimestamp] - self.startPlayChorusMusicTs;
if (estimatedProgress >= 0 && labs(currentProgress - estimatedProgress) > 50) {
// When the playback progress exceeds 50ms, make adjustments.
[[subCloud getAudioEffectManager] seekMusicToPosInMS:self.currentPlayMusicID pts:estimatedProgress];
}