How do I play a video on tvOS for Apple TV?
Asked Answered
J

6

25

I started a blank tvOS project and created the following code:

- (void)viewDidLoad  
{  
    [super viewDidLoad];  

    AVPlayer *avPlayer = [AVPlayer playerWithURL:[NSURL URLWithString:@"http://www.myurl.com/myvideo.mp4"]];  
    AVPlayerLayer *avPlayerLayer = [AVPlayerLayer playerLayerWithPlayer:avPlayer];  

    avPlayerLayer.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);  
    [self.view.layer addSublayer:avPlayerLayer];  

    [avPlayer play];  
}  

Nothing happens in the simulator though once the app loads. No video, nothing, just a blank translucent screen in my Apple TV simulator.

What's the proper way to play a sample video on app launch for an Apple TV app from an HTTP source?

Junko answered 10/9, 2015 at 5:32 Comment(3)
you need video starting with https urlFishhook
after adding exceptions this snippet works fine!Bamberg
Also, you can use self.view.bounds instead of CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height).Lief
U
19

I just pasted your code in my tvOS sample project, replaced the URL and ran it.

Nothing happened. Well, except for the fact that there's a log entry telling me that App Transport Security has blocked my URL request.

So I headed to the Info.plist, disabled ATS and upon next launch the video showed up just fine.

So if you're also using a non-HTTPS URL you're very likely running into this issue which is easily fixed by either using an HTTPS URL, disabling ATS completely or allowing specific non-HTTPs URLs in your Info.plist.

P.S.: I used this video for testing.

Ungracious answered 10/9, 2015 at 8:27 Comment(3)
Thank you! Totally forgot iOS 9 now required HTTPS unless it's turned off.Junko
I am trying to play a local file, and the NSLog tells me the video is there, however, nothing is being displayed. It's a simple tvOS app with a start button to execute the code above. Anything else I might be missing? (no ATS warning either) Some info about the video: ~130 mb, 1080p, codes: AAC, h.264Stilwell
Where did you see the error mentioning App Transport Security? I was getting a super generic "An unknown error occurred" on the AVPlayerItem, but the root cause was using http without specifically whitelisting the domainAmathist
C
11

You could also use TVML and TVMLJS https://developer.apple.com/library/prerelease/tvos/documentation/TVMLJS/Reference/TVJSFrameworkReference/

Adhere to the 'TVApplicationControllerDelegate' protocol and add some properties.

AppDelegate.h

@interface AppDelegate : UIResponder <UIApplicationDelegate, TVApplicationControllerDelegate>

...

@property (strong, nonatomic) TVApplicationController *appController;
@property (strong, nonatomic) TVApplicationControllerContext *appControllerContext;

Then add the following to 'didFinishLaunchingWithOptions'

AppDelegate.m

#define url @"http://localhost:8000/main.js"

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.    
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    self.appControllerContext = [[TVApplicationControllerContext alloc] init];
    NSURL *javascriptURL = [NSURL URLWithString:url];

    self.appControllerContext.javaScriptApplicationURL= javascriptURL;

    for (id key in launchOptions) {
        id val=[launchOptions objectForKey:key];
        NSLog(@"key=%@ value=%@", key, val);
        if([val isKindOfClass:[NSString class]]) [self.appControllerContext.launchOptions objectForKey:val];

        self.appController = [[TVApplicationController alloc] initWithContext:self.appControllerContext window:self.window delegate:self];
    }

    return YES;
}

create a folder and add the following files

  • main.js
  • index.tvml

main.js

function launchPlayer() {  
   var player = new Player();  
   var playlist = new Playlist();  
   var mediaItem = new MediaItem("video", "http://trailers.apple.com/movies/focus_features/9/9-clip_480p.mov");  
   player.playlist = playlist;  
   player.playlist.push(mediaItem);  
   player.present();
   //player.play() 
}

//in application.js  
App.onLaunch = function(options) {  
   launchPlayer();  
}

careful with this url in the mediaItem

Set up a template of your choice.

index.tvml

<document>
  <alertTemplate>
      <title>…</title>
      <description>…</description>
      <button>
          <text>…</text>
      </button>
      <text>…</text>
  </alertTemplate>
</document>

open terminal and navigate to this folder then run

python -m SimpleHTTPServer 8000

make sure the port here is the port in your ObjC url. The Apple examples use 9001.

See these tutorials for more info

http://jamesonquave.com/blog/developing-tvos-apps-for-apple-tv-with-swift/ http://jamesonquave.com/blog/developing-tvos-apps-for-apple-tv-part-2/

One issue I ran into was trying to play a local video file. It wouldn't work and there were constraint issues etc. It looks like you can't use python to play the videos so either try apache or link to a video on the web. This SO answer pointed me there.

Cinchona answered 13/9, 2015 at 15:56 Comment(0)
A
6

The best way to play video in your app on AppleTV is going to be AVKit's AVPlayerViewController. If you use AVKit, you get a lot of stuff for free.

https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVPlayerViewController_Class/index.html

You simply add that player to the viewController's player property:

// instantiate here or in storyboard
AVPlayerViewController *viewController = [[AVPlayerViewController alloc] initWithNibName:nil bundle:nil];
viewController.player = player;

[self addChildViewController:viewController];
[self.view addSubview:viewController.view];
[viewController didMoveToParentViewController:self];

// setup constraints, etc.

// play the video
[player play];

Also as mentioned below, make sure the video you're trying to play is coming either from an HTTPS connection or that you've disabled App Transport Security by setting the proper flags in the plist.

Aught answered 10/9, 2015 at 13:38 Comment(1)
This is also a good answer (but not exactly relevant to the question), because using AVPlayerViewController lets you use the default Apple TV controls. Thanks!Junko
M
5

I didn't like the answers which messed about with subviews etc. For full-screen playback, I use the following (Non-ARC) code:

// Play the stream
NSString *wifiStreamAddress = @"http://yourmoviefile.m3u8";
AVPlayer *player = [[AVPlayer alloc] initWithURL: [NSURL URLWithString: wifiStreamAddress] ];
AVPlayerViewController *playerViewController = [[AVPlayerViewController alloc] init];
playerViewController.player = player;

// Keep pointers to player and controller using retained properties:
self.player = player;
self.playerViewController = playerViewController;

[player release];
[playerViewController release];

[self presentViewController: playerViewController animated: true completion: ^{
    [self.player play];
}];

This works really neat, animating presentation and fading back to previous view when you tap the MENU button. Also, it works great with the remote control using all the standard functions.

Mele answered 11/10, 2015 at 17:4 Comment(1)
Just ended implementing this solution after reading the rest, and works like charmImprecise
B
1

Its working for me. May be helpful for you

 -(void)playAction
    {
   AVPlayerViewController *viewController = [[AVPlayerViewController    alloc] initWithNibName:nil bundle:nil];

   viewController.player = player;

  [self addChildViewController:viewController];

   [self.view addSubview:viewController.view];

   [viewController didMoveToParentViewController:self];

   // play the video

   [player play];

}
Biffin answered 29/12, 2015 at 6:13 Comment(1)
While this code may answer the question, it is better to explain what it does and add some references to it.Wits
H
-1

Swift version Make a PlayViewController which inherit the AVPlayerViewController. In the viewcontroller which has play button, add such function

@IBAction func onClickPlay(sender: AnyObject) {
    let playerVC = PlayerViewController()
    playerVC.playVideo(urlString)
    [self.presentViewController(playerVC, animated: true, completion: nil)]
}

In the PlayerViewController

func playVimeoVideo(link : String) {

    player = AVPlayer(URL: NSURL(string: link)!)   
    player?.play()
}

Notice The question and some answers may be a little misleading so that you might think that only the url with ".mp4" at the end can be played by the Apple TV. I believed so at the first time I saw the post. It is not true. In fact, with AVPlayerViewController you can play Vimeo streaming video! The link to the stream video is not like https://vimeo.com/92655878. It is possible to get it from Vimeo site by extracting it from a json file, which can be downloaded from this link

let link = "https://vimeo.com/api/oembed.json?url=https%3A//vimeo.com/" + videoId

To be able to get correct url for the video, you need to use the Vimeo Pro user access to get the stream link for a specific video.

Hawes answered 4/5, 2016 at 5:11 Comment(3)
Can you provide all the details? where to get the JSON stream?Suddenly
You can start a new question then I will answer you more details. There is not much space here.Hawes
Why don't you just edit your answer adding other details? the question has been already written here. Thank you.Suddenly

© 2022 - 2024 — McMap. All rights reserved.