API 使用示例具体使用,参考「FunctionList」- 「APIDemo」文件夹内组件范例
头文件 | 功能说明 |
---|---|
TuSDKTSAudioMixer.h | 对多音频进行混合,可设置每个音频的播放音量,播放时间范围 |
TuSDKTSAudio.h | 音频数据对象 |
设置多音频数据
// mainAudio
NSURL *mainAudioURL = [self fileURLWithName:@"sound_cat.mp3"];
_mainAudio = [[TuSDKTSAudio alloc]initWithAudioURL:mainAudioURL];
_mainAudio.audioVolume = 0;
_mainAudio.atTimeRange = [TuSDKTimeRange makeTimeRangeWithStartSeconds:0 endSeconds:6];
// audio1
NSURL *firstMixAudioURL = [self fileURLWithName:@"sound_children.mp3"];
_firstMixAudio = [[TuSDKTSAudio alloc]initWithAudioURL:firstMixAudioURL];
_firstMixAudio.audioVolume = 0;
_firstMixAudio.atTimeRange = [TuSDKTimeRange makeTimeRangeWithStartSeconds:0 endSeconds:3];
// audio2
NSURL *secondMixAudioURL = [self fileURLWithName:@"sound_tangyuan.mp3"];
_secondMixAudio = [[TuSDKTSAudio alloc]initWithAudioURL:secondMixAudioURL];
_secondMixAudio.audioVolume = 0;
_secondMixAudio.atTimeRange = [TuSDKTimeRange makeTimeRangeWithStartSeconds:0 endSeconds:3];
设置音频对象的混合输出的音量大小(Demo 为了展示将初始化设置为 0,最终输出是在 seekBar 代理方法中重新赋值)
mainAudio.audioVolume = volume;
初始化音乐混合器对象,并设置相关参数
_audiomixer = [[TuSDKTSAudioMixer alloc]init];
遵守代理 TuSDKTSAudioMixerDelegate
_audiomixer.mixDelegate = self;
设置主音轨
_audiomixer.mainAudio = mainAudio;
是否允许素材循环添加 (默认 NO,即主音轨时长 9 秒,音乐素材时长 3 秒,音乐素材将会循环添加三次)
_audiomixer.enableCycleAdd = YES;
多音频开始混合
_audiomixer.mixAudios = [NSArray arrayWithObjects:firstMixAudio, secondMixAudio,nil];
[_audiomixer startMixingAudioWithCompletion:^(NSURL *fileURL, lsqAudioMixStatus status) {
_resultURL = fileURL;
}];
实现代理,获取状态变化
/**
TuSDKTSAudioMixer 音频混合状态
*/
typedef NS_ENUM(NSInteger,lsqAudioMixStatus)
{
/**
* 未知状态
*/
lsqAudioMixStatusUnknown,
/**
* 正在混合
*/
lsqAudioMixStatusMixing,
/**
* 操作完成
*/
lsqAudioMixStatusCompleted,
/**
* 操作失败
*/
lsqAudioMixStatusFailed,
/**
* 已取消
*/
lsqAudioMixStatusCancelled
};
/**
状态通知代理
@param editor editor TuSDKTSAudioMixer
@param status status lsqAudioMixStatus
*/
- (void)onAudioMix:(TuSDKTSAudioMixer *)editor statusChanged:(lsqAudioMixStatus)status {
if (status == lsqAudioMixStatusCompleted) {
[[TuSDK shared].messageHub showSuccess:@"操作完成,请点击「播放」,播放混合好的音频"];
// TODO: 启用播放按钮
//playBtn.enabled = YES;
} else if (status == lsqAudioMixStatusCancelled) {
} else if (status == lsqAudioMixStatusFailed) {
}
}
头文件 | 功能说明 |
---|---|
TuSDKTSMovieMixer.h | 对视频和多个音频进行混合 |
设置多音频数据
NSURL *firstAudioURL = [self fileURLWithName:@"sound_cat.mp3"];
AVURLAsset *firstMixAudioAsset = [AVURLAsset URLAssetWithURL:firstAudioURL options:nil];
_firstMixAudio = [[TuSDKTSAudio alloc]initWithAsset:firstMixAudioAsset];
_firstMixAudio.atTimeRange = [TuSDKTimeRange makeTimeRangeWithStartSeconds:1 endSeconds:6];
NSURL *secondAudioURL = [self fileURLWithName:@"sound_children.mp3"];
_secondMixAudio = [[TuSDKTSAudio alloc]initWithAudioURL:secondAudioURL];
_secondMixAudio.atTimeRange = [TuSDKTimeRange makeTimeRangeWithStartSeconds:1 endSeconds:6];
初始化音视频混合器的对象
NSURL *videoURL = [self filePathName:@"tusdk_sample_video.mov"];
movieMixer = [[TuSDKTSMovieMixer alloc]initWithMoviePath:videoURL.path];
遵守代理 TuSDKTSMovieMixerDelegate
movieMixer.mixDelegate = self;
是否允许音频循环( 默认 NO,即视频素材时长 9 秒,音频素材 3 秒,将音频素材循环添加三次)
movieMixer.enableCycleAdd = YES;
混合时视频的选中时间
movieMixer.videoTimeRange = [TuSDKTimeRange makeTimeRangeWithStartSeconds:1 endSeconds:20];
是否保留视频原音
movieMixer.enableVideoSound = YES;
将背景音乐素材赋值给音视频混合器
movieMixer.mixAudios = [NSArray arrayWithObjects:firstMixAudio, secondMixAudio, nil];
进行混合
[movieMixer startMovieMixWithCompletionHandler:^(NSString *filePath, lsqMovieMixStatus status) {
if (status == lsqMovieMixStatusCompleted) {
// 操作成功 保存到相册
UISaveVideoAtPathToSavedPhotosAlbum(filePath, nil, nil, nil);
}else{
// 提示失败
NSLog(@"保存失败");
}
}];
实现代理,获取状态变化
/**
TuSDKTSMovieMixer 音视频混合状态
*/
typedef NS_ENUM(NSInteger,lsqMovieMixStatus)
{
/**
* 未知状态
*/
lsqMovieMixStatusUnknown,
/**
* 正在混合
*/
lsqMovieMixStatusMixing,
/**
* 操作完成
*/
lsqMovieMixStatusCompleted,
/**
* 操作失败
*/
lsqMovieMixStatusFailed,
/**
* 已取消
*/
lsqMovieMixStatusCancelled
};
- (void)onMovieMixer:(TuSDKTSMovieMixer *)editor statusChanged:(lsqMovieMixStatus)status;
{
if (status == lsqMovieMixStatusCompleted)
{
}
}
头文件 | 功能说明 |
---|---|
TuSDKVideoImageExtractor.h | 获取视频的缩略图数组或某一时间点的视频帧图片,支持设置获取的图片张数或者获取图片的时间间隔 ,缩略图最大图片尺寸 |
获取视频的地址
NSURL *videoURL = [self filePathName:@"tusdk_sample_video.mov"];
初始化视频画面提取的工具类
imageExtractor = [TuSDKVideoImageExtractor createExtractor];
将视频地址赋值给对象
imageExtractor.videoPath = videoURL;
设置需要返回的缩略图的数量
imageExtractor.extractFrameCount = 15;
需要输出缩略图的最大尺寸,(默认设置 : 80 * 80 )
imageExtractor.outputMaxImageSize = CGSizeMake(100, 100);
返回 <UIImage *>NSArray,数组中即为视频的缩略图
[imageExtractor asyncExtractImageList:^(NSArray<UIImage *> * images) {
// 获取到返回的视频的缩略图
weakSelf.thumbnails = images;
}];
精准时间的 API 示例展示
头文件 | 功能说明 |
---|---|
TuSDKAssetVideoComposer.h | 多个视频合并为一个视频,可设定输出文件格式,输出视频码率 |
用户不设置视频输出尺寸,则取多个视频中最小的视频尺寸进行输出
为了保证最终生成的视频效果,请尽量使用相同尺寸和视频格式的视频进行拼接
初始化视频合成器,遵守代理 TuSDKAssetVideoComposerDelegate,添加输入视频,设定输出参数
_movieComposer = [[TuSDKAssetVideoComposer alloc] initWithAsset:nil];
_movieComposer.delegate = self;
// 指定输出文件格式
_movieComposer.outputFileType = lsqFileTypeMPEG4;
// 指定输出文件的码率
_movieComposer.outputVideoQuality = [TuSDKVideoQuality makeQualityWith:TuSDKRecordVideoQuality_Low1];
// 指定输出文件的尺寸,设定后会根据输出尺寸对原视频进行裁剪
// _movieComposer.outputSize = CGSizeMake(720, 1280);
// 添加待拼接的视频源
[_movieComposer addInputAsset:[AVAsset assetWithURL:_firstInputURL]];
// 添加待拼接的视频源
[_movieComposer addInputAsset:[AVAsset assetWithURL:_secondInputURL]];
开始合并视频
[_movieComposer startComposing];
结果获取
/**
视频合成完毕
@param composer TuSDKAssetVideoComposer
@param result TuSDKVideoResult
*/
-(void)assetVideoComposer:(TuSDKAssetVideoComposer *)composer saveResult:(TuSDKVideoResult *)result {
// 视频处理结果
NSLog(@"result path: %@ ", result.videoPath);
}
获取状态变化
/**
合成状态改变事件
@param composer TuSDKAssetVideoComposer
@param status lsqAssetVideoComposerStatus 当前状态
*/
-(void)assetVideoComposer:(TuSDKAssetVideoComposer *)composer statusChanged:(TuSDKAssetVideoComposerStatus)status {
switch (status) {
case TuSDKAssetVideoComposerStatusStarted:
break;
case TuSDKAssetVideoComposerStatusCompleted:
[[TuSDK shared].messageHub showSuccess:@"操作完成,请去相册查看视频"];
break;
case TuSDKAssetVideoComposerStatusFailed:
[[TuSDK shared].messageHub showError:@"操作失败,无法生成视频文件"];
break;
case TuSDKAssetVideoComposerStatusCancelled:
[[TuSDK shared].messageHub showError:@"出现问题,操作被取消"];
break;
default:
break;
}
}
头文件 | 功能说明 |
---|---|
TuSDKMovieClipper.h | 移除一个视频中的某个时间段或多个时间段的内容,支持无音轨输出 |
初始化视频裁剪工具,并赋值 inputURL
_movieClipper = [[TuSDKMovieClipper alloc] initWithMoviePath:_inputURL.path];
是否保留视频原音
_movieClipper.enableVideoSound = YES;
遵守代理 TuSDKMovieClipperDelegate
_movieClipper.clipDelegate = self;
输出视频的文件格式,可输出 MP4
_movieClipper.outputFileType = lsqFileTypeQuickTimeMovie;
将时间范围的数组赋值给视频裁剪工具
NSMutableArray *dropArr = [[NSMutableArray alloc]init];
if (_startTime >= 0) {
TuSDKTimeRange *cutTimeRange1 = [TuSDKTimeRange makeTimeRangeWithStartSeconds:0 endSeconds:_startTime];
[dropArr addObject:cutTimeRange1];
}
if (_endTime < CMTimeGetSeconds(_item.duration)) {
TuSDKTimeRange *cutTimeRange2 = [TuSDKTimeRange makeTimeRangeWithStartSeconds:_endTime endSeconds:CMTimeGetSeconds(_item.duration)];
[dropArr addObject:cutTimeRange2];
}
_movieClipper.dropTimeRangeArr = dropArr;
进行视频裁剪
[_movieClipper startClippingWithCompletionHandler:^(NSString *outputFilePath, lsqMovieClipperSessionStatus status) {
if (status == lsqMovieClipperSessionStatusCompleted){
// 操作成功 保存到相册
UISaveVideoAtPathToSavedPhotosAlbum(outputFilePath, nil, nil, nil);
}else if(status == lsqMovieClipperSessionStatusFailed || status == lsqMovieClipperSessionStatusCancelled || status == lsqMovieClipperSessionStatusUnknown){
}
}];
状态通知
/**
TuSDKMovieClipper 视频裁剪状态
*/
typedef NS_ENUM(NSInteger,lsqMovieClipperSessionStatus)
{
/**
* 未知状态
*/
lsqMovieClipperSessionStatusUnknown,
/**
* 正在裁剪
*/
lsqMovieClipperSessionStatusClipping,
/**
* 裁剪完成
*/
lsqMovieClipperSessionStatusCompleted,
/**
* 保存失败
*/
lsqMovieClipperSessionStatusFailed,
/**
* 已取消
*/
lsqMovieClipperSessionStatusCancelled
};
- (void)onMovieClipper:(TuSDKMovieClipper *)editor statusChanged:(lsqMovieClipperSessionStatus)status;
{
if (status == lsqMovieClipperSessionStatusCompleted)
{
}
}
头文件 | 功能说明 |
---|---|
TuSDKTSAudioRecorder.h | 录制音频,支持设置最大录制时长 |
初始化录音对象
_audioRecorder = [[TuSDKTSAudioRecorder alloc]init];
设置可以录制的最大时长
_audioRecorder.maxRecordingTime = 30;
遵守代理 TuSDKTSAudioRecoderDelegate
_audioRecorder.recordDelegate = self;
开始录音
[_audioRecorder startRecording];
暂停录音(暂停后,再次调用 startRecording,会从暂停处继续录制)
[_audioRecorder pauseRecording];
结束录音 (停止录音,并保存输出音频的临时文件地址)
[_audioRecorder finishRecording];
取消录音 (停止录音,删除已录制的音频临时文件)
[_audioRecorder cancelRecording];
获取保存文件的地址
/**
结果通知代理
@param recoder recoder TuSDKTSAudioRecorder
@param result result TuSDKAudioResult
*/
- (void)onAudioRecoder:(TuSDKTSAudioRecorder *)recoder result:(TuSDKAudioResult *)result;
{
NSLog(@"result path: %@ duration : %f",result.audioPath,result.duration);
}
录音过程被打断的状态判断
// 中断开始
- (void)onAudioRecoderBeginInterruption:(TuSDKTSAudioRecorder *)recoder;
{
// 有中断时会取消录制内容 可在此做一些其他操作 如来电中断
}
// 中断已结束
- (void)onAudioRecoderEndInterruption:(TuSDKTSAudioRecorder *)recoder;
{
// 中断结束后,可进行恢复操作
}
状态通知
/**
TuSDKTSAudioRecorder 录音状态
*/
typedef NS_ENUM(NSInteger,lsqAudioRecordingStatus)
{
/**
* 未知状态
*/
lsqAudioRecordingStatusUnknown,
/**
* 正在录音
*/
lsqAudioRecordingStatusRecording,
/**
* 正在录音
*/
lsqAudioRecordingStatusPause,
/**
* 录音完成
*/
lsqAudioRecordingStatusCompleted,
/**
* 录音失败
*/
lsqAudioRecordingStatusFailed,
/**
* 已取消
*/
lsqAudioRecordingStatusCancelled
};
- (void)onAudioRecoder:(TuSDKTSAudioRecorder *)recoder statusChanged:(lsqAudioRecordingStatus)status;
{
if (status == lsqAudioRecordingStatusCompleted)
{
}
}
头文件 | 功能说明 |
---|---|
TuSDKAudioPitchEngine.h | 音频变声,支持设置不同声音效果 |
支持的音频效果
//正常
TuSDKSoundPitchNormal
//怪兽
TuSDKSoundPitchMonster
//大叔
TuSDKSoundPitchUncle
//女生
TuSDKSoundPitchGirl
//萝莉
TuSDKSoundPitchLolita
将 PCM 数据放入TuSDKAudioPitchEngine
队列中
/**
将 PCM 裸流放入 TuSDKAudioPitchEngine 缓存
@param inputBuffer 输入缓存 (PCM)
@return 是否已处理
@since v3.0
*/
- (BOOL)processInputBuffer:(CMSampleBufferRef)inputBuffer;
通知TuSDKAudioPitchEngine
输入的 PCM 音频信息变更
/** 改变输入采样格式
* @param inputInfo 输入信息
* @since v3.0
*/
- (void)changeInputAudioInfo:(TuSDKAudioTrackInfo *)inputInfo;
清除缓存并重置音频处理器
/**
* 重置 TuSDKAudioEngine
*/
-(void)reset();
释放当前音频处理器
/**
销毁 TuSDKAudioPitchEngine
@since v3.0
*/
- (void)destory;
使用示例,详见 demo/APIAudioPitchEngineRecorder
// setp1: 通过制定具体字段,初始化输入的音频信息
TuSDKAudioTrackInfo *inputInfo = [TuSDKAudioTrackInfo new];
// inputInfo.bitsPerChannel = 16; // 位宽 默认:16
// inputInfo.channelsPerFrame = 2; // 声道 默认:2
// inputInfo.sampleRate = 44100; // 声道数 默认:44100
// setp1: 通过 CMAudioFormatDescriptionRef 初始化输入的音频信息
// TuSDKAudioTrackInfo *inputInfo = [[TuSDKAudioTrackInfo alloc] initWithCMAudioFormatDescriptionRef:CMSampleBufferGetFormatDescription(CMSampleBufferRef)];
// setp2: 初始化 TuSdkAudioPitchEngine
TuSdkAudioPitchEngine audioPitchEngine = new TuSdkAudioPitchEngine(inputAudioInfo);
// setp3: 设置 TuSdkAudioPitchEngine 处理回调
audioPitchEngine.delegate = id<TuSDKAudioPitchEngineDelegate>;
// setp4: 设置当前需要的音效
audioPitchEngine.pitchType = TuSDKSoundPitchGirl;
// setp5: 将需要处理的 PCM 数据放入 TuSdkAudioPitchEngine 队列
[audioPitchEngine processInputBuffer:CMSampleBufferRef];
// setp6: 实现 TuSDKAudioPitchEngineDelegate 异步接收处理后的音频数据
/**
@param pitchEngine 音频处理对象
@param outputBuffer 变调变速后的音频数据
@param autoRelease 是否释放音频数据,默认为NO
*/
- (void)pitchEngine:(TuSDKAudioPitchEngine *)pitchEngine syncAudioPitchOutputBuffer:(CMSampleBufferRef)outputBuffer autoRelease:(BOOL *)autoRelease;
{
// 在这里添加后续处理逻辑,可用于编码,播放,或写入文件。
// 标识 syncAudioPitchOutputBuffer 回调处理完成后 TuSDKAudioPitchEngine 是否自动回收 outputBuffer
// 如果后续需要对 outputBuffer 异步处理,可以将 autoRelease 设为 NO,或对 outputBuffer 进行 deep copy,防止 syncAudioPitchOutputBuffer 处理完成后h被回收。
*autoRelease = YES;
}