草庐IT

swift 3 : issue with AVVideoCompositionCoreAnimationTool to add watermark on video

coder 2023-09-16 原文

以下代码可以完美地使用 AVVideoCompositionCoreAnimationTool 向视频添加 Logo 和文本。然后 Swift 3 来了!现在有时视频会显示带有 Logo 和文本,有时视频在导出时不显示。

let videoComposition: AVMutableVideoComposition = AVMutableVideoComposition()

    videoComposition.frameDuration = CMTimeMake(1, 60)
    videoComposition.renderSize = CGSize(width: clipVideoTrack.naturalSize.height, height: clipVideoTrack.naturalSize.height)


    let instruction: AVMutableVideoCompositionInstruction = AVMutableVideoCompositionInstruction()

    instruction.timeRange = CMTimeRangeMake(kCMTimeZero, CMTimeMakeWithSeconds(60, 30))

    // transformer is applied to set the video in portrait otherwise it is rotated by 90 degrees
    let transformer: AVMutableVideoCompositionLayerInstruction =
        AVMutableVideoCompositionLayerInstruction(assetTrack: clipVideoTrack)

    let t1: CGAffineTransform = CGAffineTransform(translationX: clipVideoTrack.naturalSize.height, y: -(clipVideoTrack.naturalSize.width - clipVideoTrack.naturalSize.height)/2)

    let t2: CGAffineTransform = t1.rotated(by: CGFloat(M_PI_2))

    var finalTransform: CGAffineTransform = t2

    transformer.setTransform(finalTransform, at: kCMTimeZero)

    instruction.layerInstructions = NSArray(object: transformer) as! [AVVideoCompositionLayerInstruction]

    videoComposition.instructions = NSArray(object: instruction) as! [AVVideoCompositionInstructionProtocol]



    let mixComposition = AVMutableComposition()
    let compositionVideoTrack = mixComposition.addMutableTrack(withMediaType: AVMediaTypeVideo, preferredTrackID: kCMPersistentTrackID_Invalid)


    do {
        try compositionVideoTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero, asset.duration), of: clipVideoTrack, at: kCMTimeZero)
    } catch {
        print(error)
    }


    //Add watermark


    let myImage = UIImage(named: "logo")

    let aLayer = CALayer()
    aLayer.contents = myImage!.cgImage
    aLayer.frame = CGRect(x: (clipVideoTrack.naturalSize.height*(self.view.bounds.width-45))/self.view.bounds.width, y: (clipVideoTrack.naturalSize.height*(self.view.bounds.width-40))/self.view.bounds.width, width: (clipVideoTrack.naturalSize.height*40)/self.view.bounds.width, height: (clipVideoTrack.naturalSize.height*40)/self.view.bounds.width)

    let titleLayer = CATextLayer()
    titleLayer.string = "text"
    titleLayer.font = UIFont(name: "helvetica", size: 0)
    titleLayer.fontSize = clipVideoTrack.naturalSize.height/16
    titleLayer.shadowOpacity = 0.5
    titleLayer.alignmentMode = kCAAlignmentCenter
    titleLayer.frame = CGRect(x: 0, y: 0, width: clipVideoTrack.naturalSize.height, height: clipVideoTrack.naturalSize.height/6)
    titleLayer.display()


    let videoSize = asset.tracks(withMediaType: AVMediaTypeVideo)[0].naturalSize
    let parentLayer = CALayer()
    let videoLayer = CALayer()
    parentLayer.frame = CGRect(x: 0, y: 0, width: videoSize.height, height: videoSize.height)
    videoLayer.frame = CGRect(x: 0, y: 0, width: videoSize.height, height: videoSize.height)

    parentLayer.addSublayer(videoLayer)
    parentLayer.addSublayer(aLayer)
    parentLayer.addSublayer(titleLayer)


    videoComposition.animationTool = AVVideoCompositionCoreAnimationTool(postProcessingAsVideoLayer: videoLayer, in: parentLayer)



    do { try FileManager.default.removeItem(at: filePath) }
    catch let error as NSError {
        NSLog("\(error), \(error.localizedDescription)")
    }



    var exportUrl: URL = filePath
    self.videoUrl = filePath as NSURL


    var exporter = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetMediumQuality)

    exporter!.videoComposition = videoComposition
    exporter!.outputFileType = AVFileTypeQuickTimeMovie
    exporter!.outputURL = URL(fileURLWithPath: exportUrl.path)


    exporter!.exportAsynchronously(completionHandler: {

        DispatchQueue.main.async {


            self.view.layer.addSublayer(self.avPlayerLayer)

            let item = AVPlayerItem(url: exportUrl)
            self.player.replaceCurrentItem(with: item)

            if (self.player.currentItem != nil) {
                print("Starting playback!")
                self.player.play()
            }

        }

    })

这在以前的 Swift 版本中可以完美地工作,但现在在 Swift 3 中不再工作了。

请注意:如果我注释掉 videoComposition.animationTool = AVVideoCompositionCoreAnimationTool(postProcessingAsVideoLayer: videoLayer, in: parentLayer) 则视频将导出并成功播放超时但没有任何覆盖。

最佳答案

看到代码在 iOS 9 上运行,这可能是 a bug in iOS 10.0其中 AVAssetExportSessions 在设置了 videoComposition 后无法正常工作。

有些人报告说 iOS 10.1 beta 中的情况看起来更好和其他人有worked around the problem .

关于 swift 3 : issue with AVVideoCompositionCoreAnimationTool to add watermark on video,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39891353/

有关swift 3 : issue with AVVideoCompositionCoreAnimationTool to add watermark on video的更多相关文章

  1. swift - 将 json 编码时间转换为 nsdate - 2

    当我将time.Now()编码到JSON对象时,它给出的结果为"2009-11-10T23:00:00Z"但打印时间。现在给出2009-11-1023:00:00+0000UTC。他们为什么不同。什么是T和Z。另外,如何根据this将其转换为swiftNSDate对象?表? 最佳答案 这些值的含义无关紧要,它们是该格式(ISO8601)的一部分。有几种方法可以解决这个问题。一种是为时间或您的结构定义自定义MarshalJSON()方法并使用它来格式化日期,另一种是首先在您的结构中将其表示为字符串,以便当默认实现执行你得到你正在寻找的

  2. objective-c - 为什么 Swift 函数定义语法是多余的? - 2

    在C/C++/Java/Go中,我们使用,来分隔参数:(aint,bint)在ObjectiveC中,我们使用:来表示参数::(int)a:(int)b在Swift中,我们必须同时使用:和,:(a:int,b:int)是否需要冗余? 最佳答案 Swift可能有外部和内部参数名称:(externalinternal:Int)如果没有独特的分隔符,会产生很多歧义。 关于objective-c-为什么Swift函数定义语法是多余的?,我们在StackOverflow上找到一个类似的问题:

  3. swift - Swift 和 Go 之间的 Zlib 压缩 - 2

    我的Swift应用程序与用Go编写的服务器通信。我希望使用Zlib压缩传输的数据,但压缩结果似乎与Swift和Go不同。这是Go版本:sourceString:="A-t-ellebesoind'autrespreuves?Acceptez-lapourleplaisir.J'aitantfaitquedelacueillir,Etc'estpresqueunefleur-des-veuves."//Compressionvarbbytes.Bufferwriter:=zlib.NewWriter(&b)writer.Write([]byte(sourceString))writer.

  4. ios - swift api SecKeyCreateEncryptedData 使用的额外认证数据是什么? - 2

    我正在使用rsaEncryptionOAEPSHA256AESGCM在iOS上使用SecKeyCreateEncryptedData加密一些数据,然后在golang后端解密相同的数据。我正在使用3072位rsa公钥来加密对称key。当我从iOS获取数据到后端时,我能够成功解密对称key,但gcm标签验证失败。我使用的是与iOS相同的16字节IV,但不知道iOS在加密时是否使用任何aad(附加身份验证数据)。有谁知道rsaEncryptionOAEPSHA256AESGCMforiOS是否使用了一些aad?这适用于iOS10+。我已经尝试过使用nil、空的16字节数组、aeskey本身、

  5. json - 如何使用 iOS Swift 访问设备中的 vpn api url? - 2

    我使用swiftyJSON从apiurl消费OData。这里的apiurl与VPN连接。并且apiurl看起来像http://192.xxx.xx.xx:8000/sap/opu/odata/sap/Z_SRV/PRListSetSet?$format=json当我在模拟器中运行时,我可以从odataapiurl获取数据,但是在设备中运行时,没有从odataapiurl接收到数据。由于没有vpn连接到移动设备。我如何以编程方式对我的VPN进行硬编码以在移动设备中接收数据?这是我如何从ODataapiurl获取数据:typealiasServiceResponse=(JSON,Error

  6. xml - 使用 XML 解析 Swift 库时,Playgrounds 崩溃并显示 "unknown error" - 2

    我正在开发一个涉及一些XML解析的自定义框架,使用Kanna框架。每当我尝试将我的框架导入playground时,playground就会崩溃并出现以下错误:Playgroundexecutionfailed:expressionfailedtoparse,unknownerror*thread#1:tid=0x4e9448,0x00000001074bf360com.apple.dt.Xcode.PlaygroundStub-macosx`executePlayground,queue='com.apple.main-thread',stopreason=breakpoint1.1*

  7. swift - 在 Windows 10 上的 Ubuntu 上的 bash 上安装 swift 4 - 2

    我尝试在Windows10上的Ubuntu上的bash上安装Swift4我的Ubuntu版本:我@DESKTOP:~$lsb_release-a没有可用的LSB模块。经销商ID:Ubuntu描述:Ubuntu16.04.3LTS发布:16.04代号:xenial我做了apt-getupgrade和apt-getupdate我遵循Linux步骤here:安装Swift4最终我得到了错误:我@DESKTOP:~$swift/home/me/swift4/swift-4.0.2-RELEASE-ubuntu16.04/usr/bin/lldb:加载共享库时出错:libpython2.7.so

  8. iOS-Swift 音视频采集与文件写入 - 2

    概述音视频采集是直播架构的第一步音视频采集包括两部分视频采集音频采集iOS开发中,同音视频采集相关API都封装在AVFoundation中,导入该框架,即可实现音频、视频的同步采集采集步骤采集步骤文字描述导入框架同采集相关API在AVFoundation中,因此需要先导入框架创建捕捉会话(AVCaptureSession)会话:用于连接输入源、输出源输入源:摄像头、麦克风输出源:对应的视频、音频数据设置视频输入源、输出源输入源(AVCaptureDeviceInput):从摄像头输入(前置/后置)输出源(AVCaptureVideoDataOutput):可从代理方法中拿到数据将输入源、输出源

  9. Swift 周报 第十六期 - 2

    前言本期是Swift编辑组自主整理周报的第七期,每个模块已初步成型。各位读者如果有好的提议,欢迎在文末留言。欢迎投稿或推荐内容。目前计划每两周周一发布,欢迎志同道合的朋友一起加入周报整理。当你来到双水村以外的大世界,你的人生目标便不单单是一名庄稼人了。Swift社区陪你一起成长,一起创造更多可能!👊👊👊周报精选新闻和社区:【挑战上岛】适配实时活动和灵动岛提案:函数反向部署Swift论坛:围绕Swift6lock展开的讨论推荐博文:推荐500+款AppUI设计工具推荐:妙言话题讨论:如果您年龄超过35岁被裁员,再入职时能接受降薪吗?新闻和社区挑战上岛:适配实时活动和灵动岛Apple大中华区设计与

  10. php - Swift Mailer 有问题不发送消息 - 2

    我的swiftmailer有问题,它没有向用户发送消息我将库提取到我网站的inc文件夹并创建了以下消息供swiftmailer发送:注意:如果您可以建议除SwiftMailer之外的其他解决方案,请发表评论。require_once'inc/lib/swift_required.php';//CreatetheTransport$transport=Swift_SmtpTransport::newInstance('mail.mywebsite.com',25)->setUsername('info@mywebsite.com')->setPassword('myPassword');

随机推荐