Reputation: 149
I would like to use VLCKit with SwiftUI.
why not AVPlayer ? because a some video formats are not supported.
Here is my code:
import SwiftUI
import UIKit
struct ContentView: View {
var body: some View {
NavigationView
{
VStack{
PlayerView(url: "https://bitdash-a.akamaihd.net/content/sintel/hls/playlist.m3u8")
}
}
}
}
struct PlayerView: UIViewRepresentable {
public var url: String
let mediaPlayer = VLCMediaPlayer()
func makeUIView(context: Context) -> UIView {
let controller = UIView()
mediaPlayer.drawable = controller
let uri = URL(string: self.url)
let media = VLCMedia(url: uri!)
mediaPlayer.media = media
mediaPlayer.play()
return controller
}
func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<PlayerView>) {
}
}
This works and load the video but I would like to add playback controls (Full Screen, Play/Pause, forward, etc.).
I didn't find any documentation about this can anyone help me a bit,
Thanks
Upvotes: 8
Views: 4841
Reputation: 31
import SwiftUI
import MobileVLCKit
///A wrapper to use MobileVLCKit media player to play and stop videos
class VLCPlayerWrapper: NSObject, ObservableObject {
var mediaPlayer: VLCMediaPlayer?
@Published var isPlaying: Bool = false
@Published var isBuffering: Bool = false
override init() {
super.init()
mediaPlayer = VLCMediaPlayer(options: ["--network-caching=5000"]) // change your media player related options
mediaPlayer?.delegate = self
}
///Method to begin playing the specified URL
func play(url: URL) {
let media = VLCMedia(url: url)
mediaPlayer?.media = media
mediaPlayer?.play()
}
///Method to stop playing the currently playing video
func stop() {
mediaPlayer?.stop()
isPlaying = false
}
func pause() {
if isPlaying {
mediaPlayer?.pause()
isPlaying = false
} else {
mediaPlayer?.play()
isPlaying = true
}
}
}
extension VLCPlayerWrapper: VLCMediaPlayerDelegate {
///Implementation for VLCMediaPlayerDelegate to handle media player state change
func mediaPlayerStateChanged(_ aNotification: Notification) {
if let player = mediaPlayer {
if player.state == .stopped {
isPlaying = false
isBuffering = false
} else if player.state == .playing {
isPlaying = true
isBuffering = false
} else if player.state == .opening {
isBuffering = true
} else if player.state == .error {
stop()
} else if player.state == .buffering {
} else if player.state == .paused {
isPlaying = false
}
}
}
}
///A wrapper which allows the MobileVLCKit to be used with SwiftUI
struct VLCMediaPlayerView: UIViewRepresentable {
typealias UIViewType = UIView
@ObservedObject var playerWrapper: VLCPlayerWrapper
///Method to create the UIKit view that is to be represented in SwiftUI
func makeUIView(context: Context) -> UIView {
let playerView = UIView()
return playerView
}
///Method to update the UIKit view that is being used in SwiftUI
func updateUIView(_ uiView: UIView, context: Context) {
if let player = playerWrapper.mediaPlayer {
player.drawable = uiView
}
}
}
struct ContentView: View {
@StateObject private var playerWrapper: VLCPlayerWrapper = VLCPlayerWrapper()
var body: some View {
ZStack(alignment: .bottom) {
VLCMediaPlayerView(playerWrapper: playerWrapper)
.overlay(alignment: .center, content: {
if self.playerWrapper.isBuffering {
VStack {
ProgressView() {
Text("Bufferning...")
.foregroundColor(.white)
.font(.headline)
}
.tint(.white)
.padding()
}
.background(.black)
.cornerRadius(20)
}
})
Spacer()
HStack {
Button(action: {
playerWrapper.play(url: /*use @State urlstring property*/)
}, label: {
Text("Play")
})
Button(action: {
playerWrapper.stop()
}, label: {
Text("Stop")
})
Button(action: {
playerWrapper.pause()
}, label: {
Text("Pause")
})
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Upvotes: 0
Reputation: 31
import SwiftUI
import MobileVLCKit
struct VLCPlayerView: UIViewRepresentable {
@Binding var mediaUrl: URL?
@State var mediaPlayer = VLCMediaPlayer()
typealias UIViewType = UIView
func makeUIView(context: Context) -> UIView {
let uiView = UIView()
mediaPlayer.drawable = uiView
return uiView
}
func updateUIView(_ uiView: UIView, context: Context) {
if let url = mediaUrl {
mediaPlayer.media = VLCMedia(url: url)
mediaPlayer.play()
} else {
mediaPlayer.stop()
}
}
}
struct ContentView: View {
@State var mediaURL: URL? //update this
var body: some View {
VLCPlayerView(mediaURL: $mediaURL)
}
}
Upvotes: 3
Reputation: 31
I watched this video on youtube https://www.youtube.com/watch?v=N_u9nsXNvn4
and this How to show my AVPlayer in a VStack with SwiftUI
Here is my demo
import SwiftUI
struct VlcPlayerDemo: UIViewRepresentable{
func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<VlcPlayerDemo>) {
}
func makeUIView(context: Context) -> UIView {
return PlayerUIView(frame: .zero)
}
}
class PlayerUIView: UIView, VLCMediaPlayerDelegate {
private let mediaPlayer = VLCMediaPlayer()
override init(frame: CGRect) {
super.init(frame: frame)
let url = URL(string: "rtsp://xxxxx")!//replace your resource here
mediaPlayer.media = VLCMedia(url: url)
mediaPlayer.delegate = self
mediaPlayer.drawable = self
mediaPlayer.play()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
}
}
struct VlcPlayerDemo_Previews: PreviewProvider {
static var previews: some View {
VlcPlayerDemo()
}
}
Upvotes: 3