SwiftUI 框架

利用 SwiftUI Video Player 在影片實時套用 Core Image 濾鏡!

iOS 14 引入了 SwiftUI Video Player ,讓我們可以在純 SwiftUI App 中做影片處理。在本篇文章中,Anupam 教大家在 VideoPlayer 實時套用 Core Image 濾鏡,為影片帶來絢麗的效果!
利用 SwiftUI Video Player 在影片實時套用 Core Image 濾鏡!
利用 SwiftUI Video Player 在影片實時套用 Core Image 濾鏡!
In: SwiftUI 框架

本篇原文(標題:SwiftUI Video Player Real-Time Processing With Core Image)刊登於作者 Medium,由 Anupam Chugh 所著,並授權翻譯及轉載。

iOS 14 的 SwiftUI 引入了播放影像檔案的原生支援。我們可以利用新的 VideoPlayer 控件,從 URLs 或本地資源中播放影像檔案。

你只需要 import AVKit,並如此傳遞 AVPlayer 實例即可:

VideoPlayer(player: AVPlayer(url: enter_url_here)

雖然 Video Player 在裝置上運作得很好,但在模擬器上可能會出問題,尤其是從網站 URL 載入中的時候。

你也可以添加客製化的疊加 (Overlay) SwiftUI 視圖到 Video Player 中。在寫這篇文章的時候,我們一定要使用預設的 Playback 控件來添加。

請注意,YouTube 的 URLs 無法在 AVPlayer 上運作,因為它們本來就是影像檔案。

Video Player 讓我們可以在純 SwiftUI App 中做影片處理,也就是說,你只需要少於 50 行程式碼,就可以寫出一個以 AI 為基礎的智能 Video Player。

在下一個部分,我們會看看如何在 Video Player 套用濾鏡,並實作一組 Core Image 濾鏡,以實時套用於影像檔案中。

如何在 SwiftUI 的 Video Player 存取影片幀

要從 AV Player 存取影片幀,最常見的方法是利用 AVPlayerItemVideoOutput。為此,我們通常會利用 CADisplayLink 計時器,以在一定的時間間隔後獲取影片幀。

CADisplayLink 並不支援 SwiftUI 的原生監聽器 (listener)。而且,如果不將 UIKit 引入,用於監聽更改的選擇器就無法操作。

因此,我們唯有選擇另一個選項:AVVideoComposition

AVVideoComposition 包含每張幀的像素緩衝 (pixel buffer)。我們在 AVPlayerItem 屬性上設定好後,就可以檢索幀並套用 CIFilter,來賦予影片一個完全不同的外觀。

在 SwiftUI 套用CIFilter 到影片串流

讓我們來建立一個新的 SwiftUI 專案,並加入以下的內容:

import SwiftUI
import AVKit
import CoreImage
import CoreImage.CIFilterBuiltins


struct ContentView: View {

    @State private var currentFilter = 0
    var filters : [CIFilter?] = [nil, CIFilter.sepiaTone(), CIFilter.pixellate(), CIFilter.comicEffect()]
    let player = AVPlayer(url: Bundle.main.url(forResource: "tennis", withExtension: "mp4")!)

    var body: some View {
        
        VStack{

        VideoPlayer(player: player)
            .onAppear{
                player.currentItem!.videoComposition = AVVideoComposition(asset: player.currentItem!.asset,  applyingCIFiltersWithHandler: { request in

                    if let filter = self.filters[currentFilter]{
                    
                    let source = request.sourceImage.clampedToExtent()
                    filter.setValue(source, forKey: kCIInputImageKey)

                    if filter.inputKeys.contains(kCIInputScaleKey){
                        filter.setValue(30, forKey: kCIInputScaleKey)
                    }

                    let output = filter.outputImage!.cropped(to: request.sourceImage.extent)
                    request.finish(with: output, context: nil)
                    }
                    else{
                        request.finish(with: request.sourceImage, context: nil)
                    }
                })
            }
            
            Picker(selection: $currentFilter, label: Text("Select Filter")) {
                ForEach(0..<filters.count) { index in
                    Text(self.filters[index]?.name ?? "None").tag(index)
                }
            }.pickerStyle(SegmentedPickerStyle())
            
            Text("Value: \(self.filters[currentFilter]?.name ?? "None")")
        }
    }
}

以上這段程式碼主要有兩件事情發生:

  • AVPlayerItem 包含 videoComposition 屬性,我們利用這個屬性設定 AVVideoComposition 的實例。在 AVVideoComposition 中,我們會傳遞 AVAsset 型別的 media 屬性。
  • applyingCIFiltersWithHandler 是對每張幀進行圖像處理的地方。我們設定把 sourceImage 傳遞到現時選擇了的 CIFilter(從 SegmentedControl 中選取)。

在本地 Video player 執行這個 App 後,就會得到套用了 4 個 CIFilters 的影片:

swiftui-video-player-1

你可以添加更多濾鏡,並設定 Slider 控件來控制濾鏡強度。如果網絡連接良好的話,添加遠程影片 URL 與使用本地視頻 URL 一樣流暢。

總結

你可以在 GitHub 儲存庫 下載這個 SwiftUI App 的完整程式碼。

有了 SwiftUI Video Player,我們可以應用很多很酷的效果,像是套用風格轉換。

本篇文章到此為止,謝謝你的閱讀。

本篇原文(標題:SwiftUI Video Player Real-Time Processing With Core Image)刊登於作者 Medium,由 Anupam Chugh 所著,並授權翻譯及轉載。

作者簡介:Anupam Chugh,深入探索 ML 及 AR 的 iOS Developer。喜愛撰寫關於想法、科技、與程式碼的文章。歡迎到我的 Blog 閱讀更多文章,或在 LinkedIn 上關注我。

譯者簡介:Kelly Chan-AppCoda 編輯小姐。

作者
AppCoda 編輯團隊
此文章為客座或轉載文章,由作者授權刊登,AppCoda編輯團隊編輯。有關文章詳情,請參考文首或文末的簡介。
評論
很好! 你已成功註冊。
歡迎回來! 你已成功登入。
你已成功訂閱 AppCoda 中文版 電子報。
你的連結已失效。
成功! 請檢查你的電子郵件以獲取用於登入的連結。
好! 你的付費資料已更新。
你的付費方式並未更新。