腾讯云短视频SDKiOS_音视频解决方案_同尘科技
本篇教程向您介绍如何从零开始完成合唱的基础功能。
过程简介
1. 在界面上放两个 View, 一个用来播放,一个用来录制。2. 再放一个按钮和进度条来开始录制和显示进度。3. 录制与源视频相同的时长后停止。4. 把录好的视频与源视频左右合成。5. 预览合成好的视频。
界面搭建
首先来开始工程的创建,打开 Xcode,File > New > Project,然后起好工程名创建工程,这里方便起见叫做 Demo,因为要录像,所以我们需要相机和麦克风的权限,在 Info 中配置一下增加以下两项:
Privacy - Microphone Usage DescriptionPrivacy - Camera Usage Description
这两项的值可以随便填写,如”录制视频”。接下来我们配置一个简单的录制界面,打开 Main.storyboard,拖进去两个 UIView,配置宽度为 superview 的0.5倍,长宽比16:9。
然后加上进度条,在 ViewController.m 中设置 IBOutlet 绑定界面,并设置好按钮的 IBAction。因为录制好后我们还要跳转到预览界面,还需要一个导航,单击黄色 VC 图标,在菜单栏依次进入 Editor > Embeded In,单击 Navigation Controller 给 ViewController 套一层 Navigation Controller。完成基本 UI 的搭建。
代码部分
对于合唱功能主要使用三大块功能:播放、录制、以及录制后和原视频进行合成,这三个功能对应到 SDK 的类为: TXVideoEditer、TXUGCRecord、TXVideoJoiner。在使用前要配置 SDK 的 Licence,打开 AppDelegate.m 在里面添加以下代码:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [TXUGCBase setLicenceURL:@"" key:@""]; return YES;}
这里的 Licence 参数需要到 短视频控制台 去申请,提交申请后一般很快就会审批下来。然后页面上就会有相关的信息。1. 首先是声明与初始化。
打开 ViewController.m,引用 SDK 并声明上述三个类的实例。另外这里播放、录制和合成视频都是异步操作,需要监听他们的事件,所以要加上实现 TXVideoJoinerListener、TXUGCRecordListener、TXVideoPreviewListener 这三个协议的声明。加好后如下所示:
#import "ViewController.h" @import TXLiteAVSDK_UGC;
@interface ViewController () { 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]; // 这里找一段 mp4 视频放到了工程里,或者用手机录制的 mov 格式视频也可以 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 = (int)(_videoInfo.fps + 0.5); //这里保证录制视频的音频采样率和合唱视频的音频采样率一致,否则可能出现音画不同步的现象 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]]; }
2. 接下来是录制部分,只要响应用户单击按钮调用 SDK 方法就可以了,为了方便起见,这里复用了这个按钮来显示当前状态。另外加上在进度条上显示进度的逻辑。
- (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; }
3. 录制好后开始完成拼接部分, 这里需要指定两个视频在结果中的位置,这里设置一左一右。
-(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]; }
4. 实现合成进度的委托方法, 在进度条中显示进度。
-(void) onJoinProgress:(float)progress { NSLog(@"视频合成中%d%%",(int)(progress * 100)); self.progressView.progress = progress; }
5. 实现合成完成的委托方法,并切换到预览界面。
#pragma mark TXVideoJoinerListener -(void) onJoinComplete:(TXJoinerResult *)result { NSLog(@"视频合成完毕"); VideoPreviewController *controller = [[VideoPreviewController alloc] initWithVideoPath:_resultPath]; [self.navigationController pushViewController:controller animated:YES]; }
到此就制作完成了,上面提到了一个视频预览的VideoPreviewController
代码如下: VideoPreviewController.h
#import
@interface VideoPreviewController : UIViewController - (instancetype)initWithVideoPath:(NSString *)path; @end
VideoPreviewController.m:
@import TXLiteAVSDK_UGC;
@interface VideoPreviewController () { 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折起,即将结束: 马上收藏
同尘科技为腾讯云授权服务中心,购买腾讯云享受折上折,更有现金返利:同意关联,立享优惠
阿里云解决方案也看看?: 点击对比阿里云的解决方案
暂无评论,你要说点什么吗?