-
Notifications
You must be signed in to change notification settings - Fork 0
/
VideoConverter.swift
158 lines (108 loc) · 4.71 KB
/
VideoConverter.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
//
// VideoConverter.swift
// Video Converter
//
// Created by Saleh AlDhobaie on 5/9/16.
// Copyright © 2016 Saleh AlDhobaie. All rights reserved.
//
import Foundation
import AVFoundation
protocol VideoConverterDelegate : class {
func videoConvertedSuccessfully(let outputVideo: VideoOutput);
func videoConvertedFailure(let error : NSError, let status: AVAssetExportSessionStatus);
}
struct VideoInput {
let inputVideoURL : NSURL?
let inputMimeType : String?
}
struct VideoOutput {
let outputVideoURL : NSURL?
let outputMimeType : String?
let format : VideoFormat?
let outputStatus : AVAssetExportSessionStatus = .Unknown
}
enum VideoFormat {
case MP4
}
enum VideoConvertError : ErrorType {
case NilVideoInput
case VideoTrackNotAvailable
case AudioTrackNotAvailable
case IssueInsertingVideo
case IssueInsertingAudio
case ExportError(String)
}
class VideoConverter : NSObject {
var videoOutput : VideoOutput? = nil
// default is true if not output file will be timestamp converting
var autoGenerateIdentifier = true
//
var ignoreAudioTrack = true
weak var delegate : VideoConverterDelegate?
override init() {
}
func convertVideo(let videoInput : VideoInput, let format : VideoFormat) throws {
guard let assetUrl = videoInput.inputVideoURL else {
throw VideoConvertError.NilVideoInput
}
let asset : AVURLAsset = AVURLAsset(URL: assetUrl);
// Create the composition and tracks
let composition = AVMutableComposition()
let videoTrack = composition.addMutableTrackWithMediaType(AVMediaTypeVideo, preferredTrackID:kCMPersistentTrackID_Invalid)
let audioTrack = composition.addMutableTrackWithMediaType(AVMediaTypeAudio, preferredTrackID: kCMPersistentTrackID_Invalid)
let tracks = asset.tracksWithMediaType(AVMediaTypeVideo)
// Extracting Video
guard let assetVideoTrack = tracks.first else {
throw VideoConvertError.VideoTrackNotAvailable
}
// Insert the tracks in the composition's tracks
do {
try videoTrack.insertTimeRange(assetVideoTrack.timeRange, ofTrack: assetVideoTrack, atTime: CMTimeMake(0, 1))
}catch let errorInsertingVideo {
print(errorInsertingVideo)
throw VideoConvertError.IssueInsertingVideo
}
videoTrack.preferredTransform = assetVideoTrack.preferredTransform;
// Extracting Audio
guard let assetAudioTrack : AVAssetTrack = asset.tracksWithMediaType(AVMediaTypeAudio).first else {
throw VideoConvertError.AudioTrackNotAvailable
}
do {
try audioTrack.insertTimeRange(assetAudioTrack.timeRange, ofTrack: assetAudioTrack, atTime: CMTimeMake(0, 1))
}catch let errorInsertingAudio {
print(errorInsertingAudio)
throw VideoConvertError.IssueInsertingAudio
}
// preparing File Name
var fileNameOutput : String = "\(NSDate().timeIntervalSinceReferenceDate)"
if autoGenerateIdentifier {
fileNameOutput = NSUUID().UUIDString
}
// Extracting Path
let outputPath = filePath(fileNameOutput)
let exportURL : NSURL = NSURL(fileURLWithPath: outputPath).URLByAppendingPathExtension("mp4");
// Export to mp4
let exportSession : AVAssetExportSession = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetPassthrough)!
exportSession.outputURL = exportURL
let startTime = CMTimeMakeWithSeconds(0.0, 0);
let range : CMTimeRange = CMTimeRangeMake(startTime, asset.duration);
exportSession.timeRange = range;
exportSession.outputFileType = AVFileTypeMPEG4
exportSession.exportAsynchronouslyWithCompletionHandler {
switch exportSession.status {
case .Completed:
let output = exportSession.outputURL!
self.videoOutput = VideoOutput(outputVideoURL:output , outputMimeType: "video/mp4", format: .MP4);
self.delegate?.videoConvertedSuccessfully(self.videoOutput!);
case .Failed:
self.delegate?.videoConvertedFailure(exportSession.error!, status: exportSession.status);
break
default :
break
}
}
}
private func filePath(let fileName : String) -> String {
return "\(NSHomeDirectory())/Documents/\(fileName)."
}
}