歡迎你們前往騰訊雲+社區,獲取更多騰訊海量技術實踐乾貨哦~canvas
本文由 視頻咖 發表於 雲+社區專欄
本文做者,shengcui,騰訊雲高級開發工程師,負責移動客戶端開發
最近抖音最近又帶了一波合唱的節奏,老闆看到後果真又是要儘快跟進,但願隔壁公司加薪的時候他也能做出如此反應。segmentfault
功能看起來不復雜,就是把一個視頻播放出來放一邊,另外一邊顯示攝像頭的畫面和源視頻一塊兒錄製。單獨錄製和播放都還比較簡單,可是左右合成就有點頭大。網上搜了一圈都是些直播相關的文章,看了下沒什麼頭緒。無奈之餘翻翻SDK碰運氣。以前作本地視頻上傳的時候有一個叫Join的類是用來先後拼接視頻的,沒想到裏面居然還有個分屏的接口,研究了一番終於弄清楚了他的使用方法。在此記錄方便回顧,也和你們一塊兒分享下。微信
以前的工程在上班以前同事就搭建好了,此次正好本身也試着搭建一遍。app
工欲善其事,必先利其器。前期的準備工做其實很少,主要是下載SDK和準備視頻。異步
大概的思路是這樣的ide
先來開始工程的建立,打開Xcode, File - New - Project, 起個好名字,這裏就叫Demo好了。網站
1建立工程ui
4配置Framework編碼
由於要錄像,因此咱們須要相機和麥克風的權限,在Info中配置一下增長如下兩項atom
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/dev...
歡迎你們前往騰訊雲+社區或關注雲加社區微信公衆號(QcloudCommunity),第一時間獲取更多海量技術實踐乾貨哦~
海量技術實踐經驗,盡在雲加社區!