欢迎你们前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~canvas
本文做者,shengcui,腾讯云高级开发工程师,负责移动客户端开发app
最近抖音最近又带了一波合唱的节奏,老板看到后果真又是要尽快跟进,但愿隔壁公司加薪的时候他也能做出如此反应。异步
功能看起来不复杂,就是把一个视频播放出来放一边,另外一边显示摄像头的画面和源视频一块儿录制。单独录制和播放都还比较简单,可是左右合成就有点头大。网上搜了一圈都是些直播相关的文章,看了下没什么头绪。无奈之余翻翻SDK碰运气。以前作本地视频上传的时候有一个叫Join的类是用来先后拼接视频的,没想到里面居然还有个分屏的接口,研究了一番终于弄清楚了他的使用方法。在此记录方便回顾,也和你们一块儿分享下。ide
以前的工程在上班以前同事就搭建好了,此次正好本身也试着搭建一遍。网站
工欲善其事,必先利其器。前期的准备工做其实很少,主要是下载SDK和准备视频。ui
大概的思路是这样的编码
先来开始工程的建立,打开Xcode, File - New - Project, 起个好名字,这里就叫Demo好了。atom
1建立工程3d
4配置Framework
由于要录像,因此咱们须要相机和麦克风的权限,在Info中配置一下增长如下两项
Privacy - Microphone Usage Description Privacy - Camera Usage Description
值的内容随便写,我填了"录像"
接下来咱们配置一个简单的录制界面,打开Main.storyboard, 拖进去两个UIView, 配置宽度为superview的0.5倍,长宽比16:9
5放View
而后加上进度条,在ViewController.m中设置IBOutlet绑定界面,并设置好按钮的IBAction。由于录制好后咱们还要跳转到预览界面,还须要一个导航,点击黄色VC图标,在菜单栏依次进入 Editor - Embeded In 点击 Navigation Controller 给ViewController套一层Navigation Controller。这样界面基本就搭建好了。
6绑定View
而后咱们就能够愉快的编码了。
前面提到过开发的思路,关键点只有三个部分,播放、录制、以及录制后和原视频进行合成,这对应到SDK的就是TXVideoEditer、TXUGCRecord、TXVideoJoiner这三个类。只要用好这三个类就能完成合唱功能了。
在使用前要配置SDK的Licence, 打开AppDelegate.m在里面添加如下代码:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [TXUGCBase setLicenceURL:@"<Licence的URL>" key:@"<Licence的Key>"]; return YES; }
这里的Licence参数须要到这里去申请,提交申请后通常很快就会审批下来。而后页面上就会有相关的信息。
打开ViewContorller.m,引用SDK并声明上述三个类的实例。另外这里播放、录制和合成视频都是异步操做,须要监听他们的事件,因此要加上实现TXVideoJoinerListener, TXUGCRecordListener, TXVideoPreviewListener这三个协议的声明。加好后以下所示。
#import "ViewController.h" @import TXLiteAVSDK_UGC; @interface ViewController () <TXVideoJoinerListener, TXUGCRecordListener, TXVideoPreviewListener> { TXVideoEditer *_editor; TXUGCRecord *_recorder; TXVideoJoiner *_joiner; TXVideoInfo *_videoInfo; NSString *_recordPath; NSString *_resultPath; } @property (weak, nonatomic) IBOutlet UIView *cameraView; @property (weak, nonatomic) IBOutlet UIView *movieView; @property (weak, nonatomic) IBOutlet UIButton *recordButton; @property (weak, nonatomic) IBOutlet UIProgressView *progressView; - (IBAction)onTapButton:(UIButton *)sender; @end
准备好成员变量和接口实现声明后,咱们在viewDidLoad中对上面的成员变量进行初始化。
- (void)viewDidLoad { [super viewDidLoad]; // 这里随便找了段视频放到了工程里 NSString *mp4Path = [[NSBundle mainBundle] pathForResource:@"demo" ofType:@"mp4"]; _videoInfo = [TXVideoInfoReader getVideoInfo:mp4Path]; TXAudioSampleRate audioSampleRate = AUDIO_SAMPLERATE_48000; if (_videoInfo.audioSampleRate == 8000) { audioSampleRate = AUDIO_SAMPLERATE_8000; }else if (_videoInfo.audioSampleRate == 16000){ audioSampleRate = AUDIO_SAMPLERATE_16000; }else if (_videoInfo.audioSampleRate == 32000){ audioSampleRate = AUDIO_SAMPLERATE_32000; }else if (_videoInfo.audioSampleRate == 44100){ audioSampleRate = AUDIO_SAMPLERATE_44100; }else if (_videoInfo.audioSampleRate == 48000){ audioSampleRate = AUDIO_SAMPLERATE_48000; } // 设置录像的保存路径 _recordPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"record.mp4"]; _resultPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"result.mp4"]; // 播放器初始化 TXPreviewParam *param = [[TXPreviewParam alloc] init]; param.videoView = self.movieView; param.renderMode = RENDER_MODE_FILL_EDGE; _editor = [[TXVideoEditer alloc] initWithPreview:param]; [_editor setVideoPath:mp4Path]; _editor.previewDelegate = self; // 录像参数初始化 _recorder = [TXUGCRecord shareInstance]; TXUGCCustomConfig *recordConfig = [[TXUGCCustomConfig alloc] init]; recordConfig.videoResolution = VIDEO_RESOLUTION_720_1280; recordConfig.videoFPS = _videoInfo.fps; recordConfig.audioSampleRate = audioSampleRate; recordConfig.videoBitratePIN = 9600; recordConfig.maxDuration = _videoInfo.duration; _recorder.recordDelegate = self; // 启动相机预览 [_recorder startCameraCustom:recordConfig preview:self.cameraView]; // 视频拼接 _joiner = [[TXVideoJoiner alloc] initWithPreview:nil]; _joiner.joinerDelegate = self; [_joiner setVideoPathList:@[_recordPath, mp4Path]]; }
- (IBAction)onTapButton:(UIButton *)sender { [_editor startPlayFromTime:0 toTime:_videoInfo.duration]; if ([_recorder startRecord:_recordPath coverPath:[_recordPath stringByAppendingString:@".png"]] != 0) { NSLog(@"相机启动失败"); } [sender setTitle:@"录像中" forState:UIControlStateNormal]; sender.enabled = NO; } #pragma mark TXVideoPreviewListener -(void) onPreviewProgress:(CGFloat)time { self.progressView.progress = time / _videoInfo.duration; }
-(void)onRecordComplete:(TXUGCRecordResult*)result; { NSLog(@"录制完成,开始合成"); [self.recordButton setTitle:@"合成中..." forState:UIControlStateNormal]; //获取录制视频的宽高 TXVideoInfo *videoInfo = [TXVideoInfoReader getVideoInfo:_recordPath]; CGFloat width = videoInfo.width; CGFloat height = videoInfo.height; //录制视频和原视频左右排列 CGRect recordScreen = CGRectMake(0, 0, width, height); CGRect playScreen = CGRectMake(width, 0, width, height); [_joiner setSplitScreenList:@[[NSValue valueWithCGRect:recordScreen],[NSValue valueWithCGRect:playScreen]] canvasWidth:width * 2 canvasHeight:height]; [_joiner splitJoinVideo:VIDEO_COMPRESSED_720P videoOutputPath:_resultPath]; }
至此就制做完成了,上面提到了一个视频预览的ViewController,代码也很简单
@import TXLiteAVSDK_UGC; @interface VideoPreviewController () <TXVideoPreviewListener> { TXVideoEditer *_editor; } @property (strong, nonatomic) NSString *videoPath; @end @implementation VideoPreviewController - (instancetype)initWithVideoPath:(NSString *)path { if (self = [super initWithNibName:nil bundle:nil]) { self.videoPath = path; } return self; } - (void)viewDidLoad { [super viewDidLoad]; TXPreviewParam *param = [[TXPreviewParam alloc] init]; param.videoView = self.view; param.renderMode = RENDER_MODE_FILL_EDGE; _editor = [[TXVideoEditer alloc] initWithPreview:param]; _editor.previewDelegate = self; [_editor setVideoPath:self.videoPath]; [_editor startPlayFromTime:0 toTime:[TXVideoInfoReader getVideoInfo:self.videoPath].duration]; } -(void) onPreviewFinished { [_editor startPlayFromTime:0 toTime:[TXVideoInfoReader getVideoInfo:self.videoPath].duration]; } @end
以上既是全部的代码,这里回顾一下前面的完整流程: 1.新建与配置工程 2.添加录像、播放与状态显示的视图 3. 响应用户事件来调用SDK相关方法 4. 响应异步操做进度的回调。一共只有百十来行代码,简直是唾手可得,再把界面修饰下明天就能够和老板报告了。老板确定没有想到我能这么完成这个任务,这对他来讲必定是一个惊喜。
问答
相关阅读
此文已由做者受权腾讯云+社区发布,原文连接:https://cloud.tencent.com/developer/article/1158911?fromSource=waitui
欢迎你们前往腾讯云+社区或关注云加社区微信公众号(QcloudCommunity),第一时间获取更多海量技术实践干货哦~
海量技术实践经验,尽在云加社区!