Ich versuche AVVideoComposition
zu verwenden, um Text über einem Video hinzuzufügen und das Video zu speichern. Dies ist der Code, den ich verwenden:Swift 3: So exportieren Sie Video mit Text mit AVVideoComposition
IErstellen Sie ein AVMutableComposition and AVVideoComposition
var mutableComp = AVMutableComposition()
var mutableVidComp = AVMutableVideoComposition()
var compositionSize : CGSize?
func configureAsset(){
let options = [AVURLAssetPreferPreciseDurationAndTimingKey : "true"]
let videoAsset = AVURLAsset(url: Bundle.main.url(forResource: "Car", withExtension: "mp4")! , options : options)
let videoAssetSourceTrack = videoAsset.tracks(withMediaType: AVMediaTypeVideo).first! as AVAssetTrack
compositionSize = videoAssetSourceTrack.naturalSize
let mutableVidTrack = mutableComp.addMutableTrack(withMediaType: AVMediaTypeVideo, preferredTrackID: kCMPersistentTrackID_Invalid)
let trackRange = CMTimeRangeMake(kCMTimeZero, videoAsset.duration)
do {
try mutableVidTrack.insertTimeRange(trackRange, of: videoAssetSourceTrack, at: kCMTimeZero)
mutableVidTrack.preferredTransform = videoAssetSourceTrack.preferredTransform
}catch { print(error) }
snapshot = mutableComp
mutableVidComp = AVMutableVideoComposition(propertiesOf: videoAsset)
}
IISetup, um die Schichten
func applyVideoEffectsToComposition() {
// 1 - Set up the text layer
let subTitle1Text = CATextLayer()
subTitle1Text.font = "Helvetica-Bold" as CFTypeRef
subTitle1Text.frame = CGRect(x: self.view.frame.midX - 60 , y: self.view.frame.midY - 50, width: 120, height: 100)
subTitle1Text.string = "Bench"
subTitle1Text.foregroundColor = UIColor.black.cgColor
subTitle1Text.alignmentMode = kCAAlignmentCenter
// 2 - The usual overlay
let overlayLayer = CALayer()
overlayLayer.addSublayer(subTitle1Text)
overlayLayer.frame = CGRect(x: 0, y: 0, width: compositionSize!.width, height: compositionSize!.height)
overlayLayer.masksToBounds = true
// 3 - set up the parent layer
let parentLayer = CALayer()
let videoLayer = CALayer()
parentLayer.frame = CGRect(x: 0, y: 0, width: compositionSize!.width, height: compositionSize!.height)
videoLayer.frame = CGRect(x: 0, y: 0, width: compositionSize!.width, height: compositionSize!.height)
parentLayer.addSublayer(videoLayer)
parentLayer.addSublayer(overlayLayer)
mutableVidComp.animationTool = AVVideoCompositionCoreAnimationTool(postProcessingAsVideoLayer: videoLayer, in: parentLayer)
}
III. Speicher Video mit AVMutbaleVideoComposition
func saveAsset(){
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).")} }
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] as URL
let filePath = documentsDirectory.appendingPathComponent("rendered-audio.mp4")
deleteFile(filePath)
if let exportSession = AVAssetExportSession(asset: mutableComp , presetName: AVAssetExportPresetHighestQuality){
exportSession.videoComposition = mutableVidComp
// exportSession.canPerformMultiplePassesOverSourceMediaData = true
exportSession.outputURL = filePath
exportSession.shouldOptimizeForNetworkUse = true
exportSession.timeRange = CMTimeRangeMake(kCMTimeZero, mutableComp.duration)
exportSession.outputFileType = AVFileTypeQuickTimeMovie
exportSession.exportAsynchronously {
print("finished: \(filePath) : \(exportSession.status.rawValue) ")
if exportSession.status.rawValue == 4 {
print("Export failed -> Reason: \(exportSession.error!.localizedDescription))")
print(exportSession.error!) }}}}
Dann laufe ich alle drei Methoden in den viewDidLoad
Verfahren für einen schnellen Test. Das Problem ist, dass wenn ich die App starte, das Ergebnis des Exports das Originalvideo ohne den Titel ist. Was fehlt mir hier?
UPDATE
Ich bemerke, dass in Teil II des Codes eine subTitle1Text.backgroundColor
Eigenschaft Hinzufügen von entsprechenden einer farbigen CGRect
macht subTitle1Text.frame
auf dem Video angezeigt, wenn exportiert. (See Image) Wenn dieser Code für die Wiedergabe mit AVSynchronizedLayer
geändert wird, kann die gewünschte Ebene über dem Video mit Text darauf angezeigt werden. Also vielleicht ist das ein Fehler in AVFoundation
selbst.
Ich nehme an, ich bin nur mit der Option der Verwendung eines customVideoCompositorClass
verlassen. Das Problem dabei ist, dass das Rendern des Videos sehr lange dauert. Hier ist ein Beispiel, das AVVideoCompositing
verwendet:
Danke für die Antwort Amrit. Ich habe meinen Code mit deiner Antwort aktualisiert, aber unglücklicherweise gibt es immer noch keinen Untertitel auf dem Video. Das Hinzufügen von AVMutableVideoCompositionInstruction scheint das Problem nicht zu lösen. Das war sehr peinlich. – 6994
check out meine aktualisierte Antwort wird es Ihnen helfen, Ihr Problem zu lösen. –
Ich habe meinen Code so geändert, dass er wieder zu Ihrer Antwort passt. Das Video wird im Simulator exportiert, aber ohne Titel im 'CATextLayer'. Nach deiner Empfehlung habe ich versucht, das Projekt auf einem Gerät auszuführen, aber das Video exportiert überhaupt nicht und wartet weiter, bis die Meldung 'aktueller Fortschritt == 0 'kontinuierlich im Debug-Bereich gedruckt wird. Ich konnte auch keinen Weg finden, dieses Problem zu lösen. – 6994