使用Objective-C中的SCRecorder以修改的播放速度保存视频

时间:2018-12-07 06:15:07

标签: ios objective-c iphone playback video-recording

使用SCRecorder希望在录制后保存视频,用户可以选择不同的回放速度:2x,3x。使用AVPlayer,可以使用以下代码实现:

//create mutable composition
AVMutableComposition *mixComposition = [AVMutableComposition composition];

AVMutableCompositionTrack *compositionVideoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo
                                                                               preferredTrackID:kCMPersistentTrackID_Invalid];
NSError *videoInsertError = nil;
BOOL videoInsertResult = [compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration)
                                                        ofTrack:[[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]
                                                         atTime:kCMTimeZero
                                                          error:&videoInsertError];
if (!videoInsertResult || nil != videoInsertError) {
    //handle error
    return;
}

//slow down whole video by 2.0
double videoScaleFactor = 2.0;
CMTime videoDuration = asset.duration;

[compositionVideoTrack scaleTimeRange:CMTimeRangeMake(kCMTimeZero, videoDuration)
                           toDuration:CMTimeMake(videoDuration.value*videoScaleFactor, videoDuration.timescale)];

//export
AVAssetExportSession* assetExport = [[AVAssetExportSession alloc] initWithAsset:mixComposition
                                                                  //   presetName:AVAssetExportPresetLowQuality];

但是,没有得到如何使用SCRecorder库实现相同的功能。请指导。 预先感谢。

2 个答案:

答案 0 :(得分:2)

最后得到了我的回答:

- (void)SlowMotion:(NSURL *)URl
{
AVURLAsset* videoAsset = [AVURLAsset URLAssetWithURL:URl options:nil];    //self.inputAsset;

AVAsset *currentAsset = [AVAsset assetWithURL:URl];
AVAssetTrack *vdoTrack = [[currentAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
//create mutable composition
AVMutableComposition *mixComposition = [AVMutableComposition composition];

AVMutableCompositionTrack *compositionVideoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
AVMutableCompositionTrack *compositionAudioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];

NSError *videoInsertError = nil;
BOOL videoInsertResult = [compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration)
                                                    ofTrack:[[videoAsset     tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]
                                                     atTime:kCMTimeZero
                                                      error:&videoInsertError];
if (!videoInsertResult || nil != videoInsertError) {
//handle error
return;
}

NSError *audioInsertError =nil;
BOOL audioInsertResult =[compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration)
                                                   ofTrack:[[currentAsset    tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0]
                                                    atTime:kCMTimeZero
                                                     error:&audioInsertError];

if (!audioInsertResult || nil != audioInsertError) {
//handle error
return;
}

CMTime duration =kCMTimeZero;
duration=CMTimeAdd(duration, currentAsset.duration);
//slow down whole video by 2.0
double videoScaleFactor = 2.0;
CMTime videoDuration = videoAsset.duration;

[compositionVideoTrack scaleTimeRange:CMTimeRangeMake(kCMTimeZero, videoDuration)
                       toDuration:CMTimeMake(videoDuration.value*videoScaleFactor, videoDuration.timescale)];
[compositionAudioTrack scaleTimeRange:CMTimeRangeMake(kCMTimeZero, videoDuration)
                       toDuration:CMTimeMake(videoDuration.value*videoScaleFactor, videoDuration.timescale)];
[compositionVideoTrack setPreferredTransform:vdoTrack.preferredTransform];

    NSArray *dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *docsDir = [dirPaths objectAtIndex:0];
    NSString *outputFilePath = [docsDir stringByAppendingPathComponent:[NSString stringWithFormat:@"slowMotion.mov"]];
    if ([[NSFileManager defaultManager] fileExistsAtPath:outputFilePath])
    [[NSFileManager defaultManager] removeItemAtPath:outputFilePath error:nil];
    NSURL *_filePath = [NSURL fileURLWithPath:outputFilePath];

//export
AVAssetExportSession* assetExport = [[AVAssetExportSession alloc] initWithAsset:mixComposition
                                                                    presetName:AVAssetExportPresetLowQuality];
assetExport.outputURL=_filePath;
                      assetExport.outputFileType =                AVFileTypeQuickTimeMovie;
exporter.shouldOptimizeForNetworkUse = YES;
                       [assetExport exportAsynchronouslyWithCompletionHandler:^
                        {

                            switch ([assetExport status]) {
                                case AVAssetExportSessionStatusFailed:
                                {
                                    NSLog(@"Export session faiied with error: %@", [assetExport error]);
                                    dispatch_async(dispatch_get_main_queue(), ^{
                                        // completion(nil);
                                    });
                                }
                                    break;
                                case AVAssetExportSessionStatusCompleted:
                                {

                                    NSLog(@"Successful");
                                    NSURL *outputURL = assetExport.outputURL;

                                    ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
                                    if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:outputURL]) {

                                        [self writeExportedVideoToAssetsLibrary:outputURL];
                                    }
                                    dispatch_async(dispatch_get_main_queue(), ^{
                                        //                                            completion(_filePath);
                                    });

                                }
                                    break;
                                default:

                                    break;
                            }


                        }];


 }

 - (void)writeExportedVideoToAssetsLibrary :(NSURL *)url {
NSURL *exportURL = url;
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:exportURL]) {
[library writeVideoAtPathToSavedPhotosAlbum:exportURL completionBlock:^(NSURL *assetURL, NSError *error){
    dispatch_async(dispatch_get_main_queue(), ^{
        if (error) {
            UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:[error localizedDescription]
                                                                message:[error localizedRecoverySuggestion]
                                                               delegate:nil
                                                      cancelButtonTitle:@"OK"
                                                      otherButtonTitles:nil];
            [alertView show];
        }
        if(!error)
        {
           // [activityView setHidden:YES];
            UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Sucess"
                                                                message:@"video added to gallery successfully"
                                                               delegate:nil
                                                      cancelButtonTitle:@"OK"
                                                      otherButtonTitles:nil];
            [alertView show];
        }
 #if !TARGET_IPHONE_SIMULATOR
        [[NSFileManager defaultManager] removeItemAtURL:exportURL error:nil];
 #endif
    });
}];
} else {
NSLog(@"Video could not be exported to assets library.");
}

}

答案 1 :(得分:0)

SCVideoConfiguration具有一个属性timeScale。

您不能尝试SCAssetExportSession。以SCVideoConfiguration作为输入。

您还可以使用SCAssetExportSession,它是AVAssetExportSession的SCRecorder副本。(SCRecorder docs)

 /* The time scale of the video
 A value more than 1 will make the buffers last longer, it creates
 a slow motion effect. A value less than 1 will make the buffers be
 shorter, it creates a timelapse effect.

 Only used in SCRecorder.
 */
@property (assign, nonatomic) CGFloat timeScale;