AVCaptureMovieFileOutput - обрезка файла при записи - PullRequest
3 голосов
/ 23 августа 2011

Я записываю видео, используя AVCaptureMovieFileOutput. Однако вместо сохранения захваченного видео в течение всего времени записи я бы хотел сохранить только последние 2 минуты видео. По сути, я хотел бы создать конечный буфер видео.

Я попытался реализовать это, установив movieFragmentInterval равным 15 секундам. Поскольку эти 15 секунд буферизуются, первые 15 секунд файла MOV будут обрезаны с использованием этого кода:

//This would be called 7 seconds after the video stream started buffering.
-(void)startTrimTimer
{
    trimTimer = [NSTimer scheduledTimerWithTimeInterval:15 target:self selector:@selector(trimFlashbackBuffer) userInfo:nil repeats:YES];
}

    -(void)trimFlashbackBuffer
    {
        //make sure that there is enough video before trimming off 15 seconds
        if(trimReadyCount<3){
            trimReadyCount++;
            return;
        }

        AVURLAsset *videoAsset = [AVURLAsset URLAssetWithURL:[NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/flashbackBuffer.MOV",tripDirectory]] options:nil]; 

        AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:videoAsset presetName:AVAssetExportPresetHighestQuality];
        exportSession.outputURL = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/flashbackBuffer.MOV",tripDirectory]];
        exportSession.outputFileType = AVFileTypeQuickTimeMovie;
        CMTimeRange timeRange = CMTimeRangeMake(CMTimeMake(15000, 1000), CMTimeMake(120000, 1000));
        exportSession.timeRange = timeRange;

        [exportSession exportAsynchronouslyWithCompletionHandler:^{
            switch (exportSession.status) {
                case AVAssetExportSessionStatusCompleted:
                    // Custom method to import the Exported Video
                    [self loadAssetFromFile:exportSession.outputURL];
                    break;
                case AVAssetExportSessionStatusFailed:
                    //
                    NSLog(@"Failed:%@",exportSession.error);
                    break;
                case AVAssetExportSessionStatusCancelled:
                    //
                    NSLog(@"Canceled:%@",exportSession.error);
                    break;
                default:
                    break;
            }
        }];

    }

Однако я получаю следующую ошибку каждый раз, когда вызывается trimFlashbackBuffer:

Failed:Error Domain=AVFoundationErrorDomain Code=-11823 "Cannot Save" UserInfo=0x12e710 {NSLocalizedRecoverySuggestion=Try saving again., NSLocalizedDescription=Cannot Save}

Это потому, что файл уже записывается AVCaptureMovieFileOutput?

Как я могу добиться эффекта бесшовного конечного видеобуфера, если этот метод не может работать?

Спасибо!

Ответы [ 2 ]

3 голосов
/ 23 августа 2011

не уверен, что то, что вы пытаетесь достичь, будет работать, потому что, как вы сказали, вы пишете файл, пытаясь его обрезать, почему вы не можете записать видео и обрезать его позже? Если вы действительно хотите просто сохранить две минуты видео в любой момент, вы можете попробовать использовать AVCaptureVideoDataOutput, используя это, вы получите видеокадры, и вы можете использовать AVAssetWriter, чтобы записать его для сжатия и записи кадров в файл, посмотрите этот SO Вопрос, который говорит о том, как это сделать Этот код для записи видео + аудио через AVAssetWriter и AVAssetWriterInputs не работает. Почему?

2 голосов
/ 27 сентября 2011

Я подозреваю, что вы получаете ошибку, потому что вы пытаетесь перезаписать тот же файл, что и в URL экспорта.Документация гласит: «Экспорт завершится неудачно, если вы попытаетесь перезаписать существующий файл или записать файл вне изолированной программной среды приложения. Если вам нужно перезаписать существующий файл, вы должны сначала удалить его».

Комуполучить последние две минуты видео, вы можете сначала получить его длительность, используя loadValuesAsynchronouslyForKeys, который является еще одним асинхронным вызовом.Используя эту продолжительность, вы можете создать временной диапазон и обрезать видео, экспортировав его в другой URL.

CMTime start = CMTimeMakeWithSeconds(durationObtained - 120, 600); 
CMTime duration = CMTimeMakeWithSeconds(120, 600);
CMTimeRange range = CMTimeRangeMake(start, duration);  
exportSession.timeRange = range;
...