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;
}