내 목표는 사용자가 사진에서 비디오를 선택하고 그 위에 레이블을 추가 할 수있게하는 것입니다.AVAssetExportSession 내보내기에 많은 시간이 필요합니다.
let audioAsset = AVURLAsset(url: selectedVideoURL)
let videoAsset = AVURLAsset(url: selectedVideoURL)
let mixComposition = AVMutableComposition()
let compositionVideoTrack = mixComposition.addMutableTrack(withMediaType: AVMediaTypeVideo, preferredTrackID: Int32(kCMPersistentTrackID_Invalid))
let compositionAudioTrack = mixComposition.addMutableTrack(withMediaType: AVMediaTypeAudio, preferredTrackID: Int32(kCMPersistentTrackID_Invalid))
let clipVideoTrack = videoAsset.tracks(withMediaType: AVMediaTypeVideo)[0]
let clipAudioTrack = audioAsset.tracks(withMediaType: AVMediaTypeAudio)[0]
do {
try compositionVideoTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero, videoAsset.duration), of: clipVideoTrack, at: kCMTimeZero)
try compositionAudioTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero, audioAsset.duration), of: clipAudioTrack, at: kCMTimeZero)
compositionVideoTrack.preferredTransform = clipVideoTrack.preferredTransform
} catch {
print(error)
}
var videoSize = clipVideoTrack.naturalSize
if isVideoPortrait(asset: videoAsset) {
videoSize = CGSize(width: videoSize.height, height: videoSize.width)
}
let parentLayer = CALayer()
let videoLayer = CALayer()
parentLayer.frame = CGRect(x: 0, y: 0, width: videoSize.width, height: videoSize.height)
videoLayer.frame = CGRect(x: 0, y: 0, width: videoSize.width, height: videoSize.height)
parentLayer.addSublayer(videoLayer)
// adding label
let helloLabelLayer = CATextLayer()
helloLabelLayer.string = "Hello"
helloLabelLayer.font = "Signika-Semibold" as CFTypeRef?
helloLabelLayer.fontSize = 30.0
helloLabelLayer.contentsScale = mainScreen.scale
helloLabelLayer.alignmentMode = kCAAlignmentNatural
helloLabelLayer.frame = CGRect(x: 0.0, y: 0.0, width: 100.0, height: 50.0)
parentLayer.addSublayer(helloLabelLayer)
// creating composition
let videoComp = AVMutableVideoComposition()
videoComp.renderSize = videoSize
videoComp.frameDuration = CMTimeMake(1, 30)
videoComp.animationTool = AVVideoCompositionCoreAnimationTool(postProcessingAsVideoLayer: videoLayer, in: parentLayer)
let instruction = AVMutableVideoCompositionInstruction()
instruction.timeRange = CMTimeRangeMake(kCMTimeZero, mixComposition.duration)
let layerInstruction = videoCompositionInstructionForTrack(track: compositionVideoTrack, asset: videoAsset)
instruction.layerInstructions = [layerInstruction]
videoComp.instructions = [instruction]
if let assetExport = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPreset640x480) {
let filename = NSTemporaryDirectory().appending("video.mov")
if FileManager.default.fileExists(atPath: filename) {
do {
try FileManager.default.removeItem(atPath: filename)
} catch {
print(error)
}
}
let url = URL(fileURLWithPath: filename)
assetExport.outputURL = url
assetExport.outputFileType = AVFileTypeMPEG4
assetExport.videoComposition = videoComp
print(NSDate().timeIntervalSince1970)
assetExport.exportAsynchronously {
print(NSDate().timeIntervalSince1970)
let library = ALAssetsLibrary()
library.writeVideoAtPath(toSavedPhotosAlbum: url, completionBlock: {
(url, error) in
switch assetExport.status {
case AVAssetExportSessionStatus.failed:
p("failed \(assetExport.error)")
case AVAssetExportSessionStatus.cancelled:
p("cancelled \(assetExport.error)")
default:
p("complete")
p(NSDate().timeIntervalSince1970)
if FileManager.default.fileExists(atPath: filename) {
do {
try FileManager.default.removeItem(atPath: filename)
} catch {
p(error)
}
}
print("Exported")
}
})
}
구현 isVideoPortrait
기능 :
func isVideoPortrait(asset: AVAsset) -> Bool {
var isPortrait = false
let tracks = asset.tracks(withMediaType: AVMediaTypeVideo)
if tracks.count > 0 {
let videoTrack = tracks[0]
let t = videoTrack.preferredTransform
if t.a == 0 && t.b == 1.0 && t.c == -1.0 && t.d == 0 {
isPortrait = true
}
if t.a == 0 && t.b == -1.0 && t.c == 1.0 && t.d == 0 {
isPortrait = true
}
if t.a == 1.0 && t.b == 0 && t.c == 0 && t.d == 1.0 {
isPortrait = false
}
if t.a == -1.0 && t.b == 0 && t.c == 0 && t.d == -1.0 {
isPortrait = false
}
}
return isPortrait
}
그리고 video composition layer instruction
의 마지막 기능은 다음과 같습니다
내가있어 무엇
func videoCompositionInstructionForTrack(track: AVCompositionTrack, asset: AVAsset) -> AVMutableVideoCompositionLayerInstruction {
let instruction = AVMutableVideoCompositionLayerInstruction(assetTrack: track)
let assetTrack = asset.tracks(withMediaType: AVMediaTypeVideo)[0]
let transform = assetTrack.preferredTransform
instruction.setTransform(transform, at: kCMTimeZero)
return instruction
}
코드는 잘 작동, 출력 비디오에는 레이블이 있지만 1 분 비디오를 선택하면 ta 28 초.
검색을 시도했지만 layerInsctuction
변형을 제거하려고했지만 효과가 없습니다.
추가 시도 : assetExport.shouldOptimizeForNetworkUse = false
아무 효과가 없습니다.
또한 AVAssetExportSession
에 AVAssetExportPresetPassthrough
을 설정하려고했는데이 경우 1 초로 비디오를 내보내지만 라벨이 사라졌습니다.
내가 갇혀 있기 때문에 도움을 주시면 감사하겠습니다. 시간 내 줘서 고마워.
시간이 많이 걸리는 작업 : 내보내기 및 사진 앨범으로 복사. 어느 것이 오래 걸리나요? – matt
또한 : 시간이 오래 걸리고 그 이유를 알고 싶으면 Instruments를 사용하십시오. 너 그거 해봤 니? 뭘 말했지? – matt
@matt 기본적으로 내보내기에는 많은 시간이 필요합니다. 사진 앨범에 복사하는 데 1 초가 걸립니다. 저는 악기를 사용하지 않았고 악기를 실행할 때 "Activity Monitor"를 사용해야합니까? – mikle94