এর আগের পোস্টে দেখেছি কিভাবে ইমেজ অথবা কালার ব্যবহার করে ফুল উইডথ ব্যাকগ্রাউন্ড ব্যবহার করা যায়। এখন দেখব কিভাবে ভিডিও ব্যাকগ্রাউন্ড হিসেবে ব্যবহার করা যায়।
তার আগে দেখি কিভাবে SwiftUI অ্যাপে ভিডিও দেখানো যায়। ভিডিও দেখাতে চাইলে প্রজেক্টে বা বান্ডেলে যে ভিডিও দেখাবো, তা কপি করতে হবে। যেমন background.mp4। এরপর VideoPlayer ভিউ ব্যবহার করে আমরা তা দেখাতে পারিঃ
import SwiftUI
import AVKit
struct ContentView: View {
var body: some View {
VideoPlayer(player: AVPlayer(url: Bundle.main.url(forResource: "background", withExtension: "mp4")!))
}
}
দেখব ভিডিও প্লে করতে পারছি। তার জন্য আমাদের AVKit ইম্পোর্ট করে নিতে হবে। VideoPlayer ভিউ ব্যবহার করে আমরা ব্যাকগ্রাউন্ডে ভিডিও সেট করতে পারব না। এর একটা প্রধাণ কারণ হচ্ছে VideoPlayer এ ডিফল্ট ভাবে প্লেয়ার কন্ট্রোল যোগ হয়।
সমাধান হচ্ছে AVPlayer ব্যবহার করা। AVPlayer হচ্ছে UIKit এর কম্পোনেন্ট। SwiftUI এর সাথে ব্যবহার করতে হলে UIViewRepresentable প্রোটোকল ব্যবহার করে একটা স্ট্রাকচার তৈরি করে নিতে হবে। যার মাধ্যমে আমরা AVPlayer ব্যবহার করতে পারব। UIViewRepresentable SwiftUI এবং UIKit এর মধ্যে ব্রিজের মত কাজ করে। UIViewRepresentable প্রটোকল ব্যবহার করলে দুইটা মেথড ইমপ্লিমেন্ট করতে হয়।
makeUIView(context:)
:- এই মেথড কল হয় যখন ভিউটা তৈরি হয়।
- এর মধ্যে UIKit এর যে ভিউটা আমরা ব্যবহার করব, তা কনফিগার করা হয়। এই ক্ষেত্রে আমরা AVPlayer ব্যবহার করব।
updateUIView(_:context:)
: এর কাজ হচ্ছে অ্যাপের স্টেট পরিবর্তন হলে UIKit ভিউ এর কোন কিছু আপডেট করা দরকার হলে সেগুলো আপডেট করে।
আমরা VideoPlayerView নামে একটা স্ট্র্যাকচার তৈরি করে নিব। যার মাধ্যমে আমরা ভিডিও অটোপ্লে হবে। এবং প্লে শেষ হয়ে গেলে পুনরায় শুরু থেকে চলবে।
import SwiftUI
import AVKit
struct VideoPlayerView: UIViewRepresentable {
var videoURL: URL
func makeUIView(context: Context) -> UIView {
let view = UIView(frame: .zero)
// Setup the player
let player = AVPlayer(url: videoURL)
let playerLayer = AVPlayerLayer(player: player)
playerLayer.videoGravity = .resizeAspectFill
playerLayer.frame = view.bounds
view.layer.addSublayer(playerLayer)
player.isMuted = true // Optional: Mute the video
player.play()
// Update the player when the view's bounds change
DispatchQueue.main.async {
playerLayer.frame = view.bounds
}
// Optional: Loop the video
NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: player.currentItem, queue: .main) { _ in
player.seek(to: .zero)
player.play()
}
return view
}
func updateUIView(_ uiView: UIView, context: Context) {
// Update frame dynamically
if let playerLayer = uiView.layer.sublayers?.first as? AVPlayerLayer {
playerLayer.frame = uiView.bounds
}
}
}
এবার এই ভিউ আমরা ব্যাকগ্রাউন্ড ভিডিও প্লেয়ার হিসেবে ব্যবহার করবঃ
import SwiftUI
import AVKit
struct ContentView: View {
var body: some View {
ZStack {
VideoPlayerView(videoURL: Bundle.main.url(forResource: "background", withExtension: "mp4")!)
.ignoresSafeArea()
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(.tint)
Text("Hello, world!")
}
}
}
}
খেয়াল রাখতে হবে প্রজেক্ট ডিরেক্টরি বা বান্ডেলে যেন নির্দিষ্ট নামে এবং নির্দিষ্ট এক্সটেনশনের ভিডিও থাকে। সোর্স কোড গিটহাবে পাওয়া যাবে। আইওএস অ্যাপ ডেভেলপমেন্ট নিয়ে অন্যান্য লেখা।
উপরের কোডে আমরা ভিডিও প্লে রিস্টার্ট করেছি NotificationCenter ব্যবহার করে। আমরা চাইলে
AVPlayerLooper ব্যবহার করেও ভিডিও প্লে রিস্টার্ট করতে পারি। সে ক্ষেত্রে নিচের ভিউ ব্যবহার করতে পারেনঃ
import SwiftUI
import AVKit
struct VideoPlayerView: UIViewRepresentable {
var videoURL: URL
private let looperContainer = LooperContainer()
func makeUIView(context: Context) -> UIView {
let view = UIView(frame: .zero)
// Create an AVQueuePlayer for looping
let player = AVQueuePlayer()
let playerItem = AVPlayerItem(url: videoURL)
// Assign the looper to keep it alive
looperContainer.looper = AVPlayerLooper(player: player, templateItem: playerItem)
// Setup the player
let playerLayer = AVPlayerLayer(player: player)
playerLayer.videoGravity = .resizeAspectFill
playerLayer.frame = view.bounds
view.layer.addSublayer(playerLayer)
// Start playback
player.isMuted = true
player.play()
// Ensure playerLayer dynamically resizes
DispatchQueue.main.async {
playerLayer.frame = view.bounds
}
return view
}
func updateUIView(_ uiView: UIView, context: Context) {
if let playerLayer = uiView.layer.sublayers?.first as? AVPlayerLayer {
playerLayer.frame = uiView.bounds
}
}
}
// Helper class to hold the looper
private class LooperContainer {
var looper: AVPlayerLooper?
}