tencent cloud

短视频 SDK

动态与公告
产品动态
关于短视频 SDK “startPlay”接口名变更的公告
产品简介
产品概述
产品功能
应用场景
基本概念
购买指南
价格总览
退款说明
免费测试
License 指引
新增与续期 License
配置查看 License
Demo 体验
SDK 下载
SDK 下载
发布日志(App)
含 UI 集成方案
小视频 App
源码解读(iOS)
源码解读(Android)
不含 UI 集成方案
SDK 集成
拍照和录制
预览裁剪和拼接
上传和播放
美颜特效
高级功能和特效
API 文档
短视频编辑
短视频录制
技术支持
错误码表
功能答疑
常见问题
上传常见问题
Android 编译问题
Android 常见问题
iOS 常见问题
License 常见问题
UGSV 政策
隐私政策
数据处理和安全协议

iOS

PDF
聚焦模式
字号
最后更新时间: 2022-05-24 16:25:50
本篇教程向大家介绍如何从零开始完成合唱的基础功能。

过程简介

1. 在界面上放两个 View, 一个用来播放,一个用来录制。
2. 再放一个按钮和进度条来开始录制和显示进度。
3. 录制与源视频相同的时长后停止。
4. 把录好的视频与源视频左右合成。
5. 预览合成好的视频。

界面搭建

首先来开始工程的创建,打开 Xcode,File > New > Project,然后起好工程名创建工程,这里方便起见叫做 Demo,因为要录像,所以我们需要相机和麦克风的权限,在 Info 中配置一下增加以下两项:
Privacy - Microphone Usage Description
Privacy - 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:@"<Licence的URL>" key:@"<Licence的Key>"];
return YES;
}
这里的 Licence 参数需要到 短视频控制台 去申请,提交申请后一般很快就会审批下来。然后页面上就会有相关的信息。
1. 首先是声明与初始化。
打开 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];
// 这里找一段 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.m:
#import <UIKit/UIKit.h>

@interface VideoPreviewController : UIViewController
- (instancetype)initWithVideoPath:(NSString *)path;
@end
VideoPreviewController.m:
@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
至此就完成了全部合唱的基础功能,功能更加丰富的示例可以参考 小视频源码

帮助和支持

本页内容是否解决了您的问题?

填写满意度调查问卷,共创更好文档体验。

文档反馈