Как добавить оверлей во время записи видео в Swift? - PullRequest
0 голосов
/ 11 ноября 2019

Я пытаюсь записать, а затем сохранить видео в Swift, используя AVFoundation. Это работает. Я также пытаюсь добавить наложение, например текстовую метку с датой, к видео.

Например: сохраненное видео - это не только то, что видит камера, но и временная метка.

Вот как я сохраняю видео:

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, но это не удалось.

Я пробовал Пример Рэя Вендерлиха , а также этот вопрос переполнения стека . Наконец, я также попробовал этот урок , и все это безрезультатно.

Как добавить оверлей к моему видео, которое находится в сохраненном видео в ролике камеры?

Ответы [ 2 ]

0 голосов
/ 15 ноября 2019

Без дополнительной информации звучит так, будто вы запрашиваете ВОДЯНУ. Не наложение.

Водяной знак - это разметка на видео, которая будет сохранена вместе с видео. Наложение обычно отображается в виде подпредставлений на слое предварительного просмотра и не сохраняется с видео.

Проверьте это здесь: 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
    }
})

Дайте мне знать, если этот код работает для вас. Это в быстрой 3, поэтому некоторые изменения будут необходимы. В настоящее время я использую этот код в моем приложении. Еще не обновил его до swift 5

0 голосов
/ 15 ноября 2019

У меня нет реальной среды разработки для Swift, которая могла бы использовать AVFoundation. Таким образом, я не могу предоставить вам пример кода.

Для добавления метаданных (дата, местоположение, отметка времени, водяной знак, частота кадров и т. Д.) В качестве наложения на видео во время записи вам потребуется обработать видеопоток, кадр за кадром, в прямом эфирево время записи. Скорее всего, вам придется хранить кадры в буфере и обрабатывать их до того, как они действительно будут записаны.

Теперь, когда дело доходит до метаданных, есть два типа, статический и динамический. Для статического типа, такого как водяной знак, это должно быть достаточно просто, поскольку все кадры получат одно и то же.

Однако для динамического типа метаданных, такого как метка времени или местоположение 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

Добавление водяного знака в текущую запись видео и сохранение с водяным знаком

Рендеринг динамического текста на CVPixelBufferRef во время записи видео

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...