所属平台 | GitHub 地址 |
iOS | |
Android | |
Flutter |
- [AppDelegate application:didFinishLaunchingWithOptions:]
中)进行如下设置:- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {NSString * const licenceURL = @"<获取到的licenseUrl>";NSString * const licenceKey = @"<获取到的key>";// V2TXLivePremier 位于 "V2TXLivePremier.h" 头文件中[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);}
V2TXLivePusher
对象,需要指定对应的 V2TXLiveMode
。// 指定对应的直播协议为 RTMP,该协议不支持连麦V2TXLivePusher *pusher = [[V2TXLivePusher alloc] initWithLiveMode:V2TXLiveMode_RTMP];
#import "SampleHandler.h"@import TXLiteAVSDK_ReplayKitExt;@implementation SampleHandler- (void)broadcastStartedWithSetupInfo:(NSDictionary<NSString *,NSObject *> *)setupInfo {// App group ID,此处 ID 与 V2TXLivePusher startScreenCapture 对应,可以指定为 nil,但按照文档设置会使功能更加可靠。[[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
// appGroup 主 App 与 Broadcast 共享的 Application Group Identifier,可以指定为 nil,但按照文档设置会使功能更加可靠。[livePusher startScreenCapture:@"group.com.xxx"];[livePusher startMicrophone];// 根据推流协议传入对应的 URL 即可启动推流, RTMP 协议以 rtmp:// 开头,该协议不支持连麦NSString * const url = @"rtmp://test.com/live/streamid?txSecret=xxxxx&txTime=xxxxxxxx";V2TXLiveCode code = [livePusher startPush:url];if (code != V2TXLIVE_OK) {// 请检查错误码}
startPush
接口返回V2TXLIVE_ERROR_INVALID_LICENSE
,则代表您的 License 校验失败了,请检查 第2步:给 SDK 配置 License 授权 中回调onLicenceLoaded
的错误码和错误描述。BOOL landScape; //YES:横屏, NO:竖屏V2TXLiveVideoEncoderParam *videoParam = [[V2TXLiveVideoEncoderParam alloc] init];videoParam.videoResolution = V2TXLiveVideoResolution960x540;videoParam.videoResolutionMode = landScape ? V2TXLiveVideoResolutionModeLandscape : V2TXLiveVideoResolutionModePortrait;[livePusher setVideoQuality:videoParam];
(x, y, scale)
参数设置的是水印图片相对于推流分辨率的归一化坐标。假设推流分辨率为:540 × 960,该字段设置为:(0.1,0.1,0.1)
,那么水印的实际像素坐标为:(540 × 0.1,960 × 0.1,水印宽度 × 0.1,水印高度会被自动计算)。// 设置视频水印[livePusher setWatermark:image x:0 y:0 scale:1];
V2TXLivePusher
对象同一时刻只能有一个在运行,所以结束推流时要做好清理工作。// 停止推流[livePusher stopScreenCapture];[livePusher stopPush];
事件 ID | 数值 | 含义说明 |
V2TXLIVE_ERROR_FAILED | -1 | 暂未归类的通用错误。 |
V2TXLIVE_ERROR_INVALID_PARAMETER | -2 | 调用 API 时,传入的参数不合法。 |
V2TXLIVE_ERROR_REFUSED | -3 | API 调用被拒绝。 |
V2TXLIVE_ERROR_NOT_SUPPORTED | -4 | 当前 API 不支持调用。 |
V2TXLIVE_ERROR_INVALID_LICENSE | -5 | license 不合法,调用失败。 |
V2TXLIVE_ERROR_REQUEST_TIMEOUT | -6 | 请求服务器超时。 |
V2TXLIVE_ERROR_SERVER_PROCESS_FAILED | -7 | 服务器无法处理您的请求。 |
事件 ID | 数值 | 含义说明 |
V2TXLIVE_WARNING_NETWORK_BUSY | 1101 | 网络状况不佳:上行带宽太小,上传数据受阻。 |
V2TXLIVE_WARNING_VIDEO_BLOCK | 2105 | 当前视频播放出现卡顿 |
V2TXLIVE_WARNING_CAMERA_START_FAILED | -1301 | 摄像头打开失败。 |
V2TXLIVE_WARNING_CAMERA_OCCUPIED | -1316 | 摄像头正在被占用中,可尝试打开其他摄像头。 |
V2TXLIVE_WARNING_CAMERA_NO_PERMISSION | -1314 | 摄像头设备未授权,通常在移动设备出现,可能是权限被用户拒绝了。 |
V2TXLIVE_WARNING_MICROPHONE_START_FAILED | -1302 | 麦克风打开失败。 |
V2TXLIVE_WARNING_MICROPHONE_OCCUPIED | -1319 | 麦克风正在被占用中,例如移动设备正在通话时,打开麦克风会失败。 |
V2TXLIVE_WARNING_MICROPHONE_NO_PERMISSION | -1317 | 麦克风设备未授权,通常在移动设备出现,可能是权限被用户拒绝了。 |
V2TXLIVE_WARNING_SCREEN_CAPTURE_NOT_SUPPORTED | -1309 | 当前系统不支持屏幕分享。 |
V2TXLIVE_WARNING_SCREEN_CAPTURE_START_FAILED | -1308 | 开始录屏失败,如果在移动设备出现,可能是权限被用户拒绝了。 |
V2TXLIVE_WARNING_SCREEN_CAPTURE_INTERRUPTED | -7001 | 录屏被系统中断。 |
- (void)broadcastStartedWithSetupInfo:(NSDictionary<NSString *,NSObject *> *)setupInfo {[self sendLocalNotificationToHostAppWithTitle:@"腾讯云录屏推流" msg:@"录屏已开始,请从这里单击回到Demo->录屏幕推流->设置推流URL与横竖屏和清晰度" 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;// 在设定时间后推送本地推送UNTimeIntervalNotificationTrigger* trigger = [UNTimeIntervalNotificationTriggertriggerWithTimeInterval:0.1f repeats:NO];UNNotificationRequest* request = [UNNotificationRequest requestWithIdentifier:@"ReplayKit2Demo"content:content trigger:trigger];//添加推送成功后的处理![center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {}];}
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){//转到 cocoa 层框架处理[[NSNotificationCenter defaultCenter] postNotificationName:@"Cocoa_ReplayKit2_Push_Start" object:nil];}- (void)handleReplayKit2PushStartNotification:(NSNotification*)noti{//通过 NSUserDefault 或剪贴板拿到宿主要传递的数据// 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];}
本页内容是否解决了您的问题?