Last active
October 21, 2021 06:19
-
-
Save nickv2002/b7bb28cdccc000bdb910 to your computer and use it in GitHub Desktop.
Swift code to play YouTube videos on AppleTV tvOS via a TVJS call using XCDYouTubeKit
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Created by Nick Vance on 12/4/15. | |
// Copyright © 2015 ToWatchList. All rights reserved. | |
// | |
import AVKit | |
import XCDYouTubeKit | |
import TVMLKit | |
class YTPlayerViewController: AVPlayerViewController, AVPlayerViewControllerDelegate { | |
//call this method once after setting up your appController. | |
func createPlayYT( appController:TVApplicationController ){ | |
//allows us to access the javascript context | |
appController.evaluateInJavaScriptContext({(evaluation: JSContext) -> Void in | |
//this is the block that will be called when javascript calls playYTblock(videoIdentifier) | |
let playYTblock : @convention(block) (String) -> Void = { | |
(videoIdentifier : String) -> Void in | |
print("Playing YouTube Video with ID:", videoIdentifier) | |
let playerViewController = AVPlayerViewController() | |
if var topController = UIApplication.sharedApplication().keyWindow?.rootViewController { | |
while let presentedViewController = topController.presentedViewController { | |
topController = presentedViewController | |
} | |
// topController should now be your topmost view controller | |
topController.presentViewController(playerViewController, animated: true, completion: nil) | |
XCDYouTubeClient.defaultClient().getVideoWithIdentifier(videoIdentifier) { [weak playerViewController] (video: XCDYouTubeVideo?, error: NSError?) in | |
if let streamURL = (video?.streamURLs[XCDYouTubeVideoQualityHTTPLiveStreaming] ?? | |
video?.streamURLs[XCDYouTubeVideoQuality.HD720.rawValue] ?? | |
video?.streamURLs[XCDYouTubeVideoQuality.Medium360.rawValue] ?? | |
video?.streamURLs[XCDYouTubeVideoQuality.Small240.rawValue]) { | |
playerViewController?.player = AVPlayer(URL: streamURL) | |
playerViewController?.player?.play() | |
playerViewController?.player?.actionAtItemEnd = AVPlayerActionAtItemEnd.None | |
NSNotificationCenter.defaultCenter().addObserver(self, | |
selector: "playerItemDidReachEnd:", | |
name: AVPlayerItemDidPlayToEndTimeNotification, | |
object: playerViewController?.player?.currentItem) | |
} else { | |
self.dismissViewControllerAnimated(true, completion: nil) | |
} | |
} | |
} | |
} | |
//this creates a function in the javascript context called "playYTblock". | |
//calling playYTblock(videoIdentifier) in javascript will call the block we created above. | |
evaluation.setObject(unsafeBitCast(playYTblock, AnyObject.self), forKeyedSubscript: "playYTblock") | |
}, completion: {(Bool) -> Void in | |
//evaluation block finished running | |
}) | |
} | |
func playerItemDidReachEnd(notification: NSNotification) { | |
print("Video reached end! Dismiss player") | |
if var topController = UIApplication.sharedApplication().keyWindow?.rootViewController { | |
while let presentedViewController = topController.presentedViewController { | |
topController = presentedViewController | |
} | |
// topController should now be your topmost view controller | |
topController.dismissViewControllerAnimated(true, completion: nil) | |
} | |
} | |
} |
Hey @nickv2002
This is a great example on how to use the XCDYouTubeKit with TVJS! I was able to integrate this gist into my app and call the playYTblock() function in my JavaScript code. Thanks for making my job a bit easier for the project I'm working on!
@ryanreece You're welcome!
Here's a gist updated for TVOS 10 based on 0xced's Stack Overflow comment.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Usage
You must call createPlayYT once after setting up your appController. I do it at the bottom of the
application
function like so:This makes the function available to call from TVJS. Then you can call it in response to a event in TVJS with something like
playYTblock(isYTWatchEvent);
(whereisYTWatchEvent
is a string with the YouTube video ID you want to play).Notes
There's probably a better way to handle the
dismissViewControllerAnimated
inplayerItemDidReachEnd
by passing the right pointer as part of the notification, but this is the first version I was able to make that worked.Code is based on these snippets: Swift XCDYouTubeKit AppleTV example, TVJS to Swift on Stack Overflow, and AVPlayerItemDidPlayToEndTimeNotification.
This requires XCDYouTubeKit version 2.4.1 or greater.