プロジェクトの概要
このFlutterアプリでは、iOSの AVPlayer を活用して動画再生を行い、FlutterのUIから再生速度を制御できます。
実装のポイント
- iOS側でAVPlayerを活用し、Flutterのみでは困難なカスタマイズを実現。
- Flutter側でスロー再生速度を指定し、AVPlayerに反映。
- 動画を中央表示するため、Flutter側から動画サイズを制御。
- AVPlayerLayerを利用したカスタムプレイヤーの構築。
iOSネイティブ実装
FlutterからiOSのAVPlayerを制御するため、 MethodChannel を用いて実装します。
AppDelegate.swift のコード
import UIKit
import Flutter
import AVFoundation
@main
@objc class AppDelegate: FlutterAppDelegate {
var videoPlayer: AVPlayer?
var playerLayer: AVPlayerLayer?
var videoWindow: UIWindow?
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
let controller = window?.rootViewController as! FlutterViewController
let channel = FlutterMethodChannel(name: "audio_processor", binaryMessenger: controller.binaryMessenger)
channel.setMethodCallHandler { [weak self] (call, result) in
guard let self = self else { return }
if call.method == "Slow" || call.method == "NotSlow" {
guard let args = call.arguments as? [String: Any],
let videoPath = args["videoPath"] as? String,
let speed = args["speed"] as? Float,
let x = args["x"] as? CGFloat,
let y = args["y"] as? CGFloat,
let width = args["width"] as? CGFloat,
let height = args["height"] as? CGFloat else {
result(FlutterError(code: "INVALID_ARGUMENTS", message: "Invalid arguments", details: nil))
return
}
self.playVideoWithLayer(mode: call.method, videoPath: videoPath, speed: speed, x: x, y: y, width: width, height: height, result: result)
} else if call.method == "Stop" {
self.stopVideo(result: result)
} else {
result(FlutterMethodNotImplemented)
}
}
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
動画の停止処理
func stopVideo(result: @escaping FlutterResult) {
DispatchQueue.main.async {
self.videoPlayer?.pause()
self.videoPlayer = nil
self.playerLayer?.removeFromSuperlayer()
self.playerLayer = nil
self.videoWindow?.isHidden = true
self.videoWindow = nil
result("停止完了")
}
}
オーディオミックスの設定
このアプリでは、再生速度に応じた適切なオーディオ処理を行うために、 AVMutableAudioMix を使用しています。速度変更時の音声の自然な変化を確保するため、audioTimePitchAlgorithm を適用し、適切なアルゴリズムを選択します。
private func configureAudioMix(for player: AVPlayer, speed: Float) {
guard let currentItem = player.currentItem,
let audioTrack = currentItem.asset.tracks(withMediaType: .audio).first else { return }
let audioMix = AVMutableAudioMix()
let audioParameters = AVMutableAudioMixInputParameters(track: audioTrack)
// 音量の設定(デフォルトは1.0)
audioParameters.setVolume(1.0, at: .zero)
// 音声のピッチ調整アルゴリズムを適用
if speed < 1.0 {
audioParameters.audioTimePitchAlgorithm = .varispeed // 低速時にピッチを自然に調整
} else {
audioParameters.audioTimePitchAlgorithm = .lowQualityZeroLatency // 通常速度時は低遅延優先
}
audioMix.inputParameters = [audioParameters]
DispatchQueue.main.async {
currentItem.audioMix = audioMix
}
}この実装により、スロー再生時には音声の高さが変わらないように調整し、通常速度では低遅延のオーディオ処理を優先することができます。
まとめ
FlutterでiOSのAVPlayerを活用し、動画のカスタマイズを行う方法について解説しました。FlutterのUIから動画のスピードや位置を制御し、iOSネイティブのAVPlayerで動画を再生することで、柔軟なカスタマイズが可能になります。
🚨 Androidは動画と音声を別々に設定する必要があるため、現時点では未対応です。