2013 이전/iOS개발

[iPhone 개발] mov 파일 mp4로 변환하기

하구루 2017. 2. 25. 16:06

안드로이드와 호환이 되는 파일 전송을 구현하다 보니 동영상 전송에 문제가 발생했다.

 
일반적으로 아이폰 비디오 레코더를 이용을 하게되면,
mov라를 확장자의 quickTimeMovie라는 방식으로 저장이 되어 진다.
이 파일을 그대로 안드로이드에 전송을 했더니
안드로이드에서는 하드웨어 코덱을 통해서는 재생을 할수가 없었다.
quick time movie 와  mpeg-4는 외부 포멧만 다를뿐 내부의 영상과 음성 코덱은 유사하다.
따라서 빠르게 변환이 가능한 방법이 있지 않을까 하고 찾다가 방법을 찾게 되었다.
바로 iOS 4 부터 지원되는 AssetLibrary를 이용하는 방법이다
이를 통해서 아래와 같이 구현해 보았다.
변환을 원하는 파일의 NSURL 과 저장을 원하는 파일 path의 NSString 을 주면 해당 path에 저장이 되게 된다.
+ (void) convertVideoQtimeToMpeg4:(NSURL *) videoURL withPath:(NSString *)videoPath {
    AVURLAsset *avAsset = [AVURLAsset URLAssetWithURL:videoURL options:nil];
    
    NSArray *compatiblePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:avAsset];

    if ([compatiblePresets containsObject:AVAssetExportPresetLowQuality]) {
        AVAssetExportSession *exportSession = [[AVAssetExportSession alloc]initWithAsset:avAsset presetName:AVAssetExportPresetPassthrough];
        
        exportSession.outputURL = [NSURL fileURLWithPath:videoPath];
        
        exportSession.outputFileType = AVFileTypeMPEG4;
        
        CMTime start = CMTimeMakeWithSeconds(0.0, 600);
        
        CMTimeRange range = CMTimeRangeMake(start, [avAsset duration]);
        
        exportSession.timeRange = range;
        
        [exportSession exportAsynchronouslyWithCompletionHandler:^{
            
            switch ([exportSession status]) {
                    
                case AVAssetExportSessionStatusFailed:
                    NSLog(@"Export failed: %@", [[exportSession error] localizedDescription]);
                    break;

               case AVAssetExportSessionStatusCompleted:
                     NSLog(@"Export Success");
                     break;
                    
                case AVAssetExportSessionStatusCancelled:
                    
                    NSLog(@"Export canceled");
                    
                    break;
                    
                default:
                    
                    break;
                    
            }
            
            [exportSession release];
            
        }];
        
    }
}

이 중에서 초기화 부분이 중요한데 presetName 에
아래처럼 AVAssetExportPresetPassthrough 를 지정해 주어야 다른 포멧으로 변환이 가능하다
 
[[AVAssetExportSession alloc]initWithAsset:avAsset presetName:AVAssetExportPresetPassthrough];
아래와 같이 AVAssetExportPresetMediumQuality 와 같은 파라미터를 주고 outputFileType를 AVFileTypeMPEG로 주게 되면 SIGNAL ABORT가 발생하고 죽게 된다.
 
 AVAssetExportSession *exportSession  = [[AVAssetExportSession alloc]initWithAsset:avAsset AVAssetExportPresetMediumQuality];

exportSession.outputFileType = AVFileTypeMPEG4;
해당 AVAssetExportSession 의 지원되는 output 포멧을 확인하고 싶을때는 AVAssetExportSession 의 supportedFileTypes propert를 통해서 확인해 볼 수가 있다.


추가로 유의 할 것은 이 방식은 asynchronous 이다.

그렇기 때문에 위와 같이 변환을 한 이후에 바로 이를 이용할수 있는것이 아니다
 [exportSession exportAsynchronouslyWithCompletionHandler:^{
            
            switch ([exportSession status]) {
                    
                case AVAssetExportSessionStatusFailed:
                    NSLog(@"Export failed: %@", [[exportSession error] localizedDescription]);
                    break;

               case AVAssetExportSessionStatusCompleted:
                     NSLog(@"Export Success");
                     break;
                    
                case AVAssetExportSessionStatusCancelled:
                    
                    NSLog(@"Export canceled");
                    
                    break;
                    
                default:
                    
                    break;
                    
            }
            
            [exportSession release];
            
        }];

당황하지 않길 바란다 이 소스는 위에 있는 전체 소스의 일부분이다. 

따라서 위 소스와 같이 exportAsynchronouslyWithCompletionHandler 를 등록하여 "AVAssetExportSessionStatusCompleted"를 확인해야 한다.

이를 꼭 유의해서 사용하기 바란다.


반응형