【问题标题】:How do you add an overlay while recording a video in Swift?在 Swift 中录制视频时如何添加叠加层?
【发布时间】:2019-11-10 21:04:45
【问题描述】:

我正在尝试使用AVFoundation 在 Swift 中录制并保存视频。这行得通。我还尝试在视频中添加叠加层,例如包含日期的文本标签。

例如:保存的视频不仅是相机看到的,还有时间戳。

这是我保存视频的方式:

func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) {
    saveVideo(toURL: movieURL!)
  }

  private func saveVideo(toURL url: URL) {
    PHPhotoLibrary.shared().performChanges({
      PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: url)
    }) { (success, error) in
      if(success) {
        print("Video saved to Camera Roll.")
      } else {
        print("Video failed to save.")
      }
    }
  }

我有一个movieOuput,即AVCaptureMovieFileOutput。我的预览图层不包含任何子图层。我尝试将时间戳标签的图层添加到 previewLayer,但没有成功。

我试过Ray Wenderlich's examplethis stack overflow question。最后,我也试过this tutorial,都无济于事。

如何在相机胶卷中保存的视频中为我的视频添加叠加层?

【问题讨论】:

标签: swift xcode avfoundation video-recording avcapturemoviefileoutput


【解决方案1】:

如果没有更多信息,听起来您要求的是水印。 不是叠加层。

水印是视频上将与视频一起保存的标记。 叠加层通常显示为预览层上的子视图,不会与视频一起保存。

在这里查看:https://stackoverflow.com/a/47742108/8272698

func addWatermark(inputURL: URL, outputURL: URL, handler:@escaping (_ exportSession: AVAssetExportSession?)-> Void) {
    let mixComposition = AVMutableComposition()
    let asset = AVAsset(url: inputURL)
    let videoTrack = asset.tracks(withMediaType: AVMediaType.video)[0]
    let timerange = CMTimeRangeMake(kCMTimeZero, asset.duration)

        let compositionVideoTrack:AVMutableCompositionTrack = mixComposition.addMutableTrack(withMediaType: AVMediaType.video, preferredTrackID: CMPersistentTrackID(kCMPersistentTrackID_Invalid))!

    do {
        try compositionVideoTrack.insertTimeRange(timerange, of: videoTrack, at: kCMTimeZero)
        compositionVideoTrack.preferredTransform = videoTrack.preferredTransform
    } catch {
        print(error)
    }

    let watermarkFilter = CIFilter(name: "CISourceOverCompositing")!
    let watermarkImage = CIImage(image: UIImage(named: "waterMark")!)
    let videoComposition = AVVideoComposition(asset: asset) { (filteringRequest) in
        let source = filteringRequest.sourceImage.clampedToExtent()
        watermarkFilter.setValue(source, forKey: "inputBackgroundImage")
        let transform = CGAffineTransform(translationX: filteringRequest.sourceImage.extent.width - (watermarkImage?.extent.width)! - 2, y: 0)
        watermarkFilter.setValue(watermarkImage?.transformed(by: transform), forKey: "inputImage")
        filteringRequest.finish(with: watermarkFilter.outputImage!, context: nil)
    }

    guard let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPreset640x480) else {
        handler(nil)

        return
    }

    exportSession.outputURL = outputURL
    exportSession.outputFileType = AVFileType.mp4
    exportSession.shouldOptimizeForNetworkUse = true
    exportSession.videoComposition = videoComposition
    exportSession.exportAsynchronously { () -> Void in
        handler(exportSession)
    }
}

以及如何调用该函数。

let outputURL = NSURL.fileURL(withPath: "TempPath")
let inputURL = NSURL.fileURL(withPath: "VideoWithWatermarkPath")
addWatermark(inputURL: inputURL, outputURL: outputURL, handler: { (exportSession) in
    guard let session = exportSession else {
        // Error 
        return
    }
    switch session.status {
        case .completed:
        guard NSData(contentsOf: outputURL) != nil else {
            // Error
            return
        }

        // Now you can find the video with the watermark in the location outputURL

        default:
        // Error
    }
})

让我知道此代码是否适合您。 它在 swift 3 中,因此需要进行一些更改。 我目前正在我的应用程序上使用此代码。还没更新到swift 5

【讨论】:

  • 现在如何添加文本更改的 UILabel?
  • @Julian Silvestri 我正在尝试录制视频,而我的相机视图顶部有图像。我遇到的问题是当我去保存视频时,图像没有显示在录制的视频中。这段代码能解决我的问题吗?谢谢。
  • 如果您正在寻找水印(与视频一起保存),那么是的
【解决方案2】:

我没有可以使用 AVFoundation 的 Swift 实际开发环境。因此,我无法为您提供任何示例代码。

要在录制时将元数据(日期、位置、时间戳、水印、帧速率等)作为叠加层添加到视频中,您必须在录制时逐帧、实时处理视频馈送.您很可能必须将帧存储在缓冲区中并在实际记录它们之前对其进行处理。

现在说到元数据,有两种类型,静态和动态。对于像水印这样的静态类型,应该很容易,因为所有帧都会得到相同的东西。

但是,对于时间戳或 GPS 位置等动态元数据类型,需要考虑一些事项。处理视频帧需要计算能力和时间。因此,取决于动态数据的类型以及获取它们的方式,有时处理的值可能不是正确的值。例如,如果您在 1:00:01 获得一帧,则处理它并为其添加时间戳。假设处理时间戳需要 2 秒。您获得的下一帧是在 1:00:02,但您要到 1:00:03 才能处理它,因为处理前一帧需要 2 秒。因此,取决于您如何获得新帧的新时间戳,该时间戳值可能不是您想要的值。

对于处理动态元数据,您还应该考虑硬件延迟。例如,该软件应该为每一帧添加实时 GPS 位置数据,并且在开发或测试中没有任何滞后。然而,在现实生活中,用户在连接不良的区域使用该软件,并且他的手机在获取他的 GPS 位置时会出现延迟。他的一些滞后时间长达 5 秒。在那种情况下你会怎么做?您是否为 GPS 定位设置了超时时间并使用了最后一个好位置?你报告错误吗?当 GPS 数据可用时,您是否推迟处理该帧(这可能会破坏实时记录)并使用昂贵的算法来尝试预测该帧的用户位置?

除了需要考虑的内容之外,我这里还有一些我认为可能对您有所帮助的参考资料。我觉得来自 medium.com 的那个看起来不错。

https://medium.com/ios-os-x-development/ios-camera-frames-extraction-d2c0f80ed05a

Adding watermark to currently recording video and save with watermark

Render dynamic text onto CVPixelBufferRef while recording video

【讨论】:

    猜你喜欢
    • 2014-10-31
    • 2015-09-15
    • 1970-01-01
    • 1970-01-01
    • 2018-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-17
    相关资源
    最近更新 更多