V2TXLivePusher
. The UIs for screen recording operations in the SDK API-Example
project are as shown below:
TXReplayKit_Screen
folder of the demo.Platform | GitHub Address |
iOS | |
Android | |
Flutter |
SampleHandler
class, which is responsible for screen recording operations.- [AppDelegate application:didFinishLaunchingWithOptions:]
):- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {NSString * const licenceURL = @"<The license URL obtained>";NSString * const licenceKey = @"<The key obtained>";// `V2TXLivePremier` is in the `V2TXLivePremier.h` header file.[V2TXLivePremier setLicence:licenceURL key:licenceKey];[V2TXLivePremier setObserver:self];NSLog(@"SDK Version = %@", [V2TXLivePremier getSDKVersionStr]);return YES;}#pragma mark - V2TXLivePremierObserver- (void)onLicenceLoaded:(int)result Reason:(NSString *)reason {NSLog(@"onLicenceLoaded: result:%d reason:%@", result, reason);}
BundleId
configured in the license must be the same as that of the application; otherwise, stream push will fail.V2TXLivePusher
componentV2TXLivePusher
object and specify V2TXLiveMode
.// Set the live streaming protocol to RTMP, which doesn't support mic connect.V2TXLivePusher *pusher = [[V2TXLivePusher alloc] initWithLiveMode:V2TXLiveMode_RTMP];
RPBroadcastSampleHandler
RPBroadcastSampleHandler
to get the screen audio/video data. Here, add the following code to the custom subclass SampleHandler.m to implement screen recording:#import "SampleHandler.h"@import TXLiteAVSDK_ReplayKitExt;@implementation SampleHandler- (void)broadcastStartedWithSetupInfo:(NSDictionary<NSString *,NSObject *> *)setupInfo {// The application group ID. The ID must match `startScreenCapture` of `V2TXLivePusher` and can be set to `nil`, but setting it as instructed in the documentation will make the feature more reliable.[[TXReplayKitExt sharedInstance] setupWithAppGroup:APPGROUP delegate:self];}- (void)broadcastPaused {// User has requested to pause the broadcast. Samples will stop being delivered.[[TXReplayKitExt sharedInstance] broadcastPaused];}- (void)broadcastResumed {// User has requested to resume the broadcast. Samples delivery will resume.[[TXReplayKitExt sharedInstance] broadcastResumed];}- (void)broadcastFinished {// User has requested to finish the broadcast.[[TXReplayKitExt sharedInstance] broadcastFinished];}- (void)processSampleBuffer:(CMSampleBufferRef)sampleBuffer withType:(RPSampleBufferType)sampleBufferType {[[TXReplayKitExt sharedInstance] sendSampleBuffer:sampleBuffer withType:sampleBufferType];}#pragma mark - TXReplayKitExtDelegate- (void)broadcastFinished:(TXReplayKitExt *)broadcast reason:(TXReplayKitExtReason)reason{NSString *tip = @"";switch (reason) {case TXReplayKitExtReasonRequestedByMain:tip = NSLocalizedString(@"MLVB-API-Example.liveStop", "");break;case TXReplayKitExtReasonDisconnected:tip = NSLocalizedString(@"MLVB-API-Example.appReset", "");break;case TXReplayKitExtReasonVersionMismatch:tip = NSLocalizedString(@"MLVB-API-Example.sdkError", "");break;}NSError *error = [NSError errorWithDomain:NSStringFromClass(self.class)code:0userInfo:@{NSLocalizedFailureReasonErrorKey:tip}];[self finishBroadcastWithError:error];}@end
RPBroadcastSampleHandler
, you need to call the corresponding method inTXReplayKitExt
to set the screen recording information and handle screen recording events.V2TXLivePusher
to start pushing the stream.RTMP
protocol for stream push in step 3, you can generate a stream push address as instructed in Quick URL Generation.// The application group ID for data sharing between the host application and Broadcast Upload Extension during screen recording on iOS. It can be set to `nil`, but setting it as instructed in our documentation will make the feature more reliable.[livePusher startScreenCapture:@"group.com.xxx"];[livePusher startMicrophone];// Pass in the corresponding URL based on the stream push protocol to start stream push. The URL for the RTMP protocol starts with `rtmp://`, which doesn't support mic connect.NSString * const url = @"rtmp://test.com/live/streamid?txSecret=xxxxx&txTime=xxxxxxxx";V2TXLiveCode code = [livePusher startPush:url];if (code != V2TXLIVE_OK) {// Check the error code}
BOOL landScape; // `YES`: Landscape; `NO`: Portrait.V2TXLiveVideoEncoderParam *videoParam = [[V2TXLiveVideoEncoderParam alloc] init];videoParam.videoResolution = V2TXLiveVideoResolution960x540;videoParam.videoResolutionMode = landScape ? V2TXLiveVideoResolutionModeLandscape : V2TXLiveVideoResolutionModePortrait;[livePusher setVideoQuality:videoParam];
V2TXLivePusher
to add a watermark to videos output by the SDK. The position of the watermark is determined by the (x, y, scale)
parameter passed in.(x, y, scale)
parameter specifies the normalized coordinates of the watermark relative to the resolution of the published video. For example, if the resolution of the published video is 540 x 960, and (x, y, scale)
is set to (0.1, 0.1, 0.1)
, the actual pixel coordinates of the watermark will be (540 x 0.1, 960 x 0.1). The width of the watermark will be the video width x 0.1, and the height will be scaled automatically.// Set the video watermark[livePusher setWatermark:image x:0 y:0 scale:1];
V2TXLivePusher
object running at a time, make sure that you release all the resources when stopping publishing.// Stop stream push[livePusher stopScreenCapture];[livePusher stopPush];
Event ID | Code | Description |
V2TXLIVE_ERROR_FAILED | -1 | A common unclassified error occurred. |
V2TXLIVE_ERROR_INVALID_PARAMETER | -2 | An invalid parameter was passed in during API calling. |
V2TXLIVE_ERROR_REFUSED | -3 | The API call was rejected. |
V2TXLIVE_ERROR_NOT_SUPPORTED | -4 | The API cannot be called. |
V2TXLIVE_ERROR_INVALID_LICENSE | -5 | Failed to call the API due to invalid license. |
V2TXLIVE_ERROR_REQUEST_TIMEOUT | -6 | The server request timed out. |
V2TXLIVE_ERROR_SERVER_PROCESS_FAILED | -7 | The server could not handle your request. |
Event ID | Code | Description |
V2TXLIVE_WARNING_NETWORK_BUSY | 1101 | Bad network connection: Data upload blocked due to limited upstream bandwidth. |
V2TXLIVE_WARNING_VIDEO_BLOCK | 2105 | Stuttering during video playback. |
V2TXLIVE_WARNING_CAMERA_START_FAILED | -1301 | Failed to turn the camera on. |
V2TXLIVE_WARNING_CAMERA_OCCUPIED | -1316 | The camera is occupied. Try a different camera. |
V2TXLIVE_WARNING_CAMERA_NO_PERMISSION | -1314 | No access to the camera. This usually occurs on mobile devices and may be because the user denied the access. |
V2TXLIVE_WARNING_MICROPHONE_START_FAILED | -1302 | Failed to turn the mic on. |
V2TXLIVE_WARNING_MICROPHONE_OCCUPIED | -1319 | The mic is occupied. This occurs when, for example, the user is currently having a call on the mobile device. |
V2TXLIVE_WARNING_MICROPHONE_NO_PERMISSION | -1317 | No access to the mic. This usually occurs on mobile devices and may be because the user denied the access. |
V2TXLIVE_WARNING_SCREEN_CAPTURE_NOT_SUPPORTED | -1309 | The system does not support screen sharing. |
V2TXLIVE_WARNING_SCREEN_CAPTURE_START_FAILED | -1308 | Failed to start screen recording. If this occurs on a mobile device, it may be because the user denied the access. |
V2TXLIVE_WARNING_SCREEN_CAPTURE_INTERRUPTED | -7001 | Screen recording was stopped by the system |
- (void)broadcastStartedWithSetupInfo:(NSDictionary<NSString *,NSObject *> *)setupInfo {[self sendLocalNotificationToHostAppWithTitle:@"Tencent Cloud Screen Sharing" msg:@"Screen recording has started. Return to Cloud Video Toolkit > MLVB > Screen Sharing to set the publishing URL, orientation, and resolution." userInfo:@{kReplayKit2UploadingKey: kReplayKit2Uploading}];}- (void)sendLocalNotificationToHostAppWithTitle:(NSString*)title msg:(NSString*)msg userInfo:(NSDictionary*)userInfo{UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];UNMutableNotificationContent* content = [[UNMutableNotificationContent alloc] init];content.title = [NSString localizedUserNotificationStringForKey:title arguments:nil];content.body = [NSString localizedUserNotificationStringForKey:msg arguments:nil];content.sound = [UNNotificationSound defaultSound];content.userInfo = userInfo;// Schedule a local notification to be sent at the specified timeUNTimeIntervalNotificationTrigger* trigger = [UNTimeIntervalNotificationTriggertriggerWithTimeInterval:0.1f repeats:NO];UNNotificationRequest* request = [UNNotificationRequest requestWithIdentifier:@"ReplayKit2Demo"content:content trigger:trigger];// Add operation after the notification is sent[center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {}];}
userInfo
field for data transfer, you must configure an app group and use NSUserDefault
for data transfer. For example, after getting the publishing URL, the host app can notify the broadcast upload extension via CFNotificationCenter that stream publishing can start. You may also use the clipboard, but delayed rendering is needed as the clipboard sometimes fails to transfer data between processes in real time.CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(),kDarvinNotificationNamePushStart,NULL,nil,YES);
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),(__bridge const void *)(self),onDarwinReplayKit2PushStart,kDarvinNotificationNamePushStart,NULL,CFNotificationSuspensionBehaviorDeliverImmediately);[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleReplayKit2PushStartNotification:) name:@"Cocoa_ReplayKit2_Push_Start" object:nil];static void onDarwinReplayKit2PushStart(CFNotificationCenterRef center,void *observer, CFStringRef name,const void *object, CFDictionaryRefuserInfo){// Send to the Cocoa layer[[NSNotificationCenter defaultCenter] postNotificationName:@"Cocoa_ReplayKit2_Push_Start" object:nil];}- (void)handleReplayKit2PushStartNotification:(NSNotification*)noti{// Get the data to be transferred by the host app via NSUserDefault or the clipboard// NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:kReplayKit2AppGroupId];UIPasteboard* pb = [UIPasteboard generalPasteboard];NSDictionary* defaults = [self jsonData2Dictionary:pb.string];s_rtmpUrl = [defaults objectForKey:kReplayKit2PushUrlKey];s_resolution = [defaults objectForKey:kReplayKit2ResolutionKey];if (s_resolution.length < 1) {s_resolution = kResolutionHD;}NSString* rotate = [defaults objectForKey:kReplayKit2RotateKey];if ([rotate isEqualToString:kReplayKit2Portrait]) {s_landScape = NO;}else {s_landScape = YES;}[self start];}
broadcastFinished
function in SampleHandler
will be invoked, and you can send a notification to users about the interruption.
Was this page helpful?