I have created a simple AVPlayer. (If I didn't create it correctly, please help me fixing it... 😀 ) I want to display it in my VStack with swift ui, but I'm kind of stuck...
If at least there was the AVPlayer View component in the library, it would have been easier, but I didn't found it in the library... 😔
Here is my code in the ContentView.swift
:
//
// ContentView.swift
// test
//
// Created by Francis Dolbec on 2019-06-26.
// Copyright © 2019 Francis Dolbec. All rights reserved.
//
import SwiftUI
import AVKit
import AVFoundation
// MARK: variables
var hauteurMenuBar = NSApplication.shared.mainMenu?.menuBarHeight
var urlVideo = URL(string: "/Users/francisdolbec/Movies/Séries Télé/Rick et Morty/Rick.and.Morty.S01E01.VFQ.HDTV.1080p.x264-Kamek.mp4")
let player = AVPlayer(url: urlVideo!)
struct ContentView : View {
var body: some View {
VStack {
Text("Hello World")
.frame(maxWidth: .infinity, maxHeight: .infinity)
Text("PATATE!")
//player.play()
}
.frame(minWidth: 1024, idealWidth: 1440, maxWidth: .infinity, minHeight: (640-hauteurMenuBar!), idealHeight: (900-hauteurMenuBar!), maxHeight: .infinity)
}
}
#if DEBUG
struct ContentView_Previews : PreviewProvider {
static var previews: some View {
ContentView()
}
}
#endif
By the way, if there's a tutorial that show how to make a video player with swift ui, I would really appreciate it!
EDIT I forgot to say that I am developing a macOS app.
Sure, here's the tutorial, by Chris Mash on Medium.
Basically you embed an AVPlayerLayer
into a struct conforming to UIViewRepresentable
, something you'll do for any UIView
component you want to use with SwiftUI.
struct PlayerView: UIViewRepresentable {
func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<PlayerView>) {
}
func makeUIView(context: Context) -> UIView {
return PlayerUIView(frame: .zero)
}
}
The "meat" of the implementation is done in the PlayerUIView
class:
class PlayerUIView: UIView {
private let playerLayer = AVPlayerLayer()
override init(frame: CGRect) {
super.init(frame: frame)
let url = URL(string: "https://bitdash-a.akamaihd.net/content/sintel/hls/playlist.m3u8")!
let player = AVPlayer(url: url)
player.play()
playerLayer.player = player
layer.addSublayer(playerLayer)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
playerLayer.frame = bounds
}
}
And then you use it like this:
var body: some View {
PlayerView()
}
Thanks to Bogdan for the quick answer and for the like to the tutorial!
Here is the code, converted to NSView so it could work for macOS apps...
Here is the struct PlayerView
:
struct PlayerView: NSViewRepresentable {
func updateNSView(_ nsView: NSView, context: NSViewRepresentableContext<PlayerView>) {
}
func makeNSView(context: Context) -> NSView {
return PlayerNSView(frame: .zero)
}
}
Here is the class, "the meat" like Bogdan said:
class PlayerNSView: NSView{
private let playerLayer = AVPlayerLayer()
override init(frame:CGRect){
super.init(frame: frame)
let urlVideo = URL(string: "https://bitdash-a.akamaihd.net/content/sintel/hls/playlist.m3u8")!
let player = AVPlayer(url: urlVideo)
player.play()
playerLayer.player = player
if layer == nil{
layer = CALayer()
}
layer?.addSublayer(playerLayer)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layout() {
super.layout()
playerLayer.frame = bounds
}
}
Finally you can use PlayerView()
to add the AVPlayer in the struct ContentView
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With