Things take time

[SWIFT] mov 파일을 mp4 파일로 변환하기 / 동영상 재생시간 구하기(double to dateformat) 본문

iOS (기능)

[SWIFT] mov 파일을 mp4 파일로 변환하기 / 동영상 재생시간 구하기(double to dateformat)

겸손할 겸 2018. 1. 30. 17:11

[로직]


동영상을 선택하란 로직에서 리턴값으로 넘어오는 값의 확장자는 .mov확장자다.

문제는 이런 동영상 파일은 아이폰에서는 정상 작동하지만, 안드로이드에서는 재생할 수 없다(물론 해당 코덱을 가진 유료 동영상 플레이어를 내장한 기기에서는 재생가능)

이럴 때 필요한 것이 서로 다른 디바이스에서 공통적으로 인식 가능하도록 확장자를 변경하여 저장하는 방법이다.


[코드]

    func encodeVideo(videoURL: URL){
        let avAsset = AVURLAsset(url: videoURL)
        let startDate = Date()
        let exportSession = AVAssetExportSession(asset: avAsset, presetName: AVAssetExportPresetPassthrough)
        
        let docDir = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first
        let myDocPath = NSURL(fileURLWithPath: docDir!).appendingPathComponent("temp.mp4")?.absoluteString
        
        let docDir2 = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] as NSURL
        let filePath = docDir2.appendingPathComponent("rendered-Video.mp4")
        deleteFile(filePath!)
        
        if FileManager.default.fileExists(atPath: myDocPath!){
            do{
                try FileManager.default.removeItem(atPath: myDocPath!)
            }catch let error{
                print(error)
            }
        }
        
        exportSession?.outputURL = filePath
        exportSession?.outputFileType = AVFileType.mp4
        exportSession?.shouldOptimizeForNetworkUse = true
        
        let start = CMTimeMakeWithSeconds(0.0, 0)
        let range = CMTimeRange(start: start, duration: avAsset.duration)
        exportSession?.timeRange = range
        exportSession!.exportAsynchronously{
            () -> Void in
            switch exportSession!.status{
            case .failed:
                print("\(exportSession!.error!)")
            case .cancelled:
                print("Export cancelled")
            case .completed:
                let endDate = Date()
                let time = endDate.timeIntervalSince(startDate)
                DispatchQueue.main.async {
                    ...
                }
            default:
                break
            }
        }
    }
    
    func deleteFile(_ filePath:URL) {
        guard FileManager.default.fileExists(atPath: filePath.path) else{
            return
        }
        do {
            try FileManager.default.removeItem(atPath: filePath.path)
        }catch{
            fatalError("Unable to delete file: \(error) : \(#function).")
        }
    }

temp.mp4란 파일이 있다면 삭제하고, rendered-Video.mp4란 파일의 유무도 판단하여 삭제한다.

전자는 자주 사용하는 문구라서 혹시나 싶어 삭제하는건가 싶기도하고, 후자는 저 이름으로 mp4 파일을 만들 것이기 때문에, 기존 것을 삭제하기 위함이다.

그리고  AVAssetExprtSession이란 변환 객체를 이용하여 변환하는 것이고, 이 결과는 비동기적으로 나오기 때문에, 추가작업이 필요하다면 메인 쓰레드에서 비동기로 작업하는 것이다. 


[추가]

해당 파일의 동영상 시간을 분:초로 표기하고 싶을때 사용하는 코드다.

                            let filePathURL = NSURL.fileURL(withPath: filePath)
                            let asset = AVURLAsset(url: filePathURL as URL)
                            let playTimeFloat = CMTimeGetSeconds(asset.duration)
                            let playTimeSum = (playTimeFloat*100).rounded()/100
                            
                            let minute = Int(playTimeSum / 60)
                            let second = Int((playTimeSum.truncatingRemainder(dividingBy: 60)).rounded())
                            let playTime = String(format: "%0d:%02d", minute, second)