Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
0
Help us understand the problem. What is going on with this article?
@fuziki

iOSでアルファチャンネル付きで動画を作成する

iOS でアルファチャンネル付きで動画を作成する

  • AVAssetWriter を使うと、iOS で透過情報付きの動画を作成する事が可能です
  • iOS の写真アプリは透過付きの動画を再生可能です
  • ツールバーの表示/非表示で背景色が変わったり、プルダウンすることで後ろの画像が見えるので、動画の背景が透過されている事がわかります

サンプルアプリ

  • リポジトリはこちらです

  • Examples/NativeExamples/NativeExamples.xcodeprojCrossMetal iOS ターゲットです
  • Xcode の Metal の Game アプリをベースにしています

透過情報付きで保存するポイント

  • AVAssetWriterInput の生成時の settings で、hevcWithAlpha を指定します
let videoConfigs: [String: Any] = [AVVideoCodecKey : AVVideoCodecType.hevcWithAlpha,
                                   AVVideoWidthKey : 1920,
                                   AVVideoHeightKey :1080]
let videoAssetWriterInput = AVAssetWriterInput(mediaType: .video, outputSettings: videoConfigs)
  • 書き込む CMSampleBuffer の CVPixelBuffer のフォーマットとして kCVPixelFormatType_32BGRA を選択します
let options = [kCVPixelBufferIOSurfacePropertiesKey: [:]] as [String : Any]            
let status = CVPixelBufferCreate(nil, width, height,
                                 kCVPixelFormatType_32BGRA,
                                 options as CFDictionary,
                                 &pixelBuffer)
  • 透過情報付きの画像データを生成し、AVAssetWriterInput に書き込むことで、アルファチャンネル付きの動画を取得可能です

実装

録画開始

  • ファイルタイプは mov を指定しました
  • hevcWithAlpha が保存できるコンテナであれば良いと思います
let assetWriter = try! AVAssetWriter(outputURL: url, fileType: AVFileType.mov)

let videoConfigs: [String: Any] = [AVVideoCodecKey : AVVideoCodecType.hevcWithAlpha,
                                   AVVideoWidthKey : 1920,
                                   AVVideoHeightKey : 1080]
let videoAssetWriterInput = AVAssetWriterInput(mediaType: .video, outputSettings: videoConfigs)
videoAssetWriterInput.expectsMediaDataInRealTime = true
assetWriter.add(videoAssetWriterInput)
  • 元の画像を Metal でレンダリングしているので、MTLTexture と描画時刻を受け取ります
  • MTLTexture -> CIImage -> CVPixelBuffer -> CMSampleBuffer の順番に変換します
func make(mtlTexture: MTLTexture, time: CMTime) -> CMSampleBuffer? {
    let ci = CIImage(mtlTexture: mtlTexture, options: nil)!
    CVPixelBufferLockBaseAddress(pixelBuffer, CVPixelBufferLockFlags(rawValue: 0))
    context.render(ci, to: pixelBuffer)
    var res: CMSampleBuffer? = nil
    var sampleTiming = CMSampleTimingInfo()
    sampleTiming.presentationTimeStamp = time
    let _ = CMSampleBufferCreateForImageBuffer(allocator: kCFAllocatorDefault,
                                               imageBuffer: pixelBuffer,
                                               dataReady: true,
                                               makeDataReadyCallback: nil,
                                               refcon: nil,
                                               formatDescription: formatDescription,
                                               sampleTiming: &sampleTiming,
                                               sampleBufferOut: &res)
    CVPixelBufferUnlockBaseAddress(pixelBuffer, CVPixelBufferLockFlags(rawValue: 0))
    return res
}
  • 作成した CMSampleBuffer を videoAssetWriterInput に書き込みます
videoAssetWriterInput.append(sample)

録画終了

  • finishWriting することで mov ファイルが作成されています
assetWriter.finishWriting(completionHandler: { })

保存

  • 指定した url に動画が保存されているので、必要に応じて保存します
  • ALAssetsLibrary は deprecated なので Photos framework を使った方が良さそうです
ALAssetsLibrary()
    .writeVideoAtPath(toSavedPhotosAlbum: url) { (url: URL?, error: Error?) in
        print("url: \(String(describing: url)), error: \(String(describing: error))")
    }

おわりに

  • アルファチャンネル付きの動画を保存可能になると、汎用性が高そうです
  • 例えば、LiDAR のデプスをアルファチャンネルに入れて保存するなど活用できそうです
  • Unity でも R8G8B8A8_UNorm など、alpha チャンネルがあるテクスチャを渡すことで、透過情報付きの動作を作成する事が可能です
0
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
0
Help us understand the problem. What is going on with this article?