Skip to content

Instantly share code, notes, and snippets.

@nickv2002
Last active October 21, 2021 06:19
Show Gist options
  • Star 11 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save nickv2002/b7bb28cdccc000bdb910 to your computer and use it in GitHub Desktop.
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
//
// 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)
}
}
}
@nickv2002
Copy link
Author

Usage

You must call createPlayYT once after setting up your appController. I do it at the bottom of the application function like so:

    let playerVC = YTPlayerViewController()
    playerVC.createPlayYT( appController! )

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); (where isYTWatchEvent is a string with the YouTube video ID you want to play).

Notes

There's probably a better way to handle the dismissViewControllerAnimated in playerItemDidReachEnd 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.

@ryanreece
Copy link

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!

@nickv2002
Copy link
Author

@ryanreece You're welcome!

@ryanreece
Copy link

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