Noccis
Noccis

Reputation: 83

Easiest way to play a video from youtube in my app with swiftui?

I am trying to make a video player in my app (with swiftUI) that playes videos from youtube when the user creates a URL string. To practise I have seperated this into a new project to see that it works. But the screen is just black with a play button. Nothing happends when I press the play button or the screen. This is my code:

import SwiftUI
import AVKit

struct ContentView: View {
    
    let url = URL(string: "https://youtu.be/Wlf1T5nrO50")!
    
    
    var body: some View {
        VStack{
           
            VideoPlayer(player: AVPlayer(url: url))
                .scaledToFit()
            
        }
}

I found another video with how to make embedded youtube videos but then you need to just copy the video ID and my user is not that advanced. I want the user to be able to just copy the URL.

Thankful for any help.

Upvotes: 3

Views: 9287

Answers (3)

Alessandro Francucci
Alessandro Francucci

Reputation: 1660

An alternative slightly different that I came up with and looks more clean is the following:

import SwiftUI
import WebKit

struct YouTubePlayerView: UIViewRepresentable {
    
    private let url: URL
    
    init?(videoID: String) {
        guard let url = URL(string: "https://www.youtube.com/embed/\(videoID)") else { return nil }
        self.init(url: url)
    }
    
    init(url: URL) {
        self.url = url
    }
    
    // MARK: Functions

    func makeUIView(context: Context) -> WKWebView {
        let webView = WKWebView()
        webView.navigationDelegate = context.coordinator
        return webView
    }

    func updateUIView(_ uiView: WKWebView, context: Context) {
        let request = URLRequest(url: url)
        uiView.load(request)
    }

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    class Coordinator: NSObject, WKNavigationDelegate {
        var parent: YouTubePlayerView

        init(_ parent: YouTubePlayerView) {
            self.parent = parent
        }
        
        func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
        }

        func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        }
    }
}

It supports the initialisation through URL or just by VideoID. updateUIView seems a better place to load the url and the coordinator allows you do perform extra actions if needed upon loading, finishing etc

Upvotes: 0

Siempay
Siempay

Reputation: 1002

A better Solution I made


struct YoutubeVideoView: UIViewRepresentable {
    
    var youtubeVideoID: String
    
    func makeUIView(context: Context) -> WKWebView  {
        
        WKWebView()
    }
    
    func updateUIView(_ uiView: WKWebView, context: Context) {
        
        let path = "https://www.youtube.com/embed/\(youtubeVideoID)"
        guard let url = URL(string: path) else { return }
        
        uiView.scrollView.isScrollEnabled = false
        uiView.load(.init(url: url))
    }
}

Upvotes: 9

RelativeJoe
RelativeJoe

Reputation: 5084

A YouTube url is not a valid video URL. You have to either add youtube's library or play it using a WKWebView.

Also check out this package, it's awesome!

Using WKWebView:

 struct LinkView: View {
    var link: String
    var body: some View {
        WebView(url: URL(string: link.embed)!)
    }
}

struct WebView: UIViewRepresentable {
    var url: URL
    func makeUIView(context: Context) -> WKWebView  {
        let webView = WKWebView()
        let request = URLRequest(url: url)
        webView.load(request)
        return webView
    }
    func updateUIView(_ uiView: WKWebView, context: Context) {
    }
}
extension String {
    var embed: String {
        var strings = self.components(separatedBy: "/")
        let videoId = strings.last ?? ""
        strings.removeLast()
        let embedURL = strings.joined(separator: "/") + "embed/\(videoId)"
        return embedURL
    }
}

Usage:

LinkView(link: "https://youtube.com/videoid")

Remember, this is a very basic WebView that does not handle errors and loading.

Upvotes: 0

Related Questions