Delay is about 10 seconds.
Snippet of my code. It's *.m file of HomeController:
#interface HomeController ()
#property(nonatomic, strong) AVPlayerViewController *playerViewController;
#implementation HomeController
- (void)viewDidLoad
{
[super viewDidLoad];
...
self.playerViewController = [[AVPlayerViewController alloc] init];
}
- (IBAction)watchDemoToggle:(id)sender {
NSURL *url = [NSURL URLWithString:#"http://blahblahblah.com/demo.mp4"];
AVURLAsset *asset = [AVURLAsset assetWithURL: url];
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:asset];
if(playerItem)
{
AVPlayer *player = [[AVPlayer alloc] initWithPlayerItem:playerItem];
self.playerViewController.player = player;
[self.playerViewController.player addObserver:self forKeyPath:#"status" options:0 context:nil];
[self.playerViewController setShowsPlaybackControls:NO];
[self presentViewController:self.playerViewController animated:YES completion:^{
[self.playerViewController.player play];
self.playerViewController.showsPlaybackControls = YES;
}];
}
}
#pragma mark - KVO
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context {
if ([keyPath isEqualToString:#"status"]) {
AVPlayerStatus status = [change[NSKeyValueChangeNewKey] integerValue];
NSLog(#"status = %ld", (long)status);
}
}
I added KVO and got result that after click play player status is AVPlayerStatusUnknown. After that it is not changing despite the fact that the video is reproducing.
Does anyone have any idea?
set automaticallyWaitsToMinimizeStalling property of AVPlayer to false in order to start playback immediately.
AVPlayer *player = [[AVPlayer alloc] initWithPlayerItem:playerItem];
player.automaticallyWaitsToMinimizeStalling = false;
But if sufficient content is not available for playing then player might stall.
for more details please refer this Apple documentation.
avplayer
Related
I have an ESP8266-CAM which I connect to my WiFi and stream it out. I have it so I can go onto any browser anywhere and type in the address http://xxx.xxxxx.xxxx.xx.xx/xxxxx/x and it will play. I have it working in a Blynk app also using this address. I would like to include it in an iPhone app I am building.
I have the following code to play the stream.
#import "ViewController.h"
#import <AVKit/AVKit.h>
#import <AVFoundation/AVFoundation.h>
#interface ViewController ()
#property (nonatomic, strong) AVPlayer *player;
#property (nonatomic,strong) AVPlayerItem * playerItem;
#property (nonatomic, strong )AVPlayerLayer *avPlayerLayer;
-(IBAction)Turnon:(id)sender;
- (void)viewDidLoad {
[super viewDidLoad];
}
-(void) startplayer
{
NSURL *url = [[NSURL alloc]initWithString:#"xxxxxxxxxxx/xxxxx/1"];
AVPlayerItem * playerItem= [AVPlayerItem playerItemWithURL:url];
self.player = [AVPlayer playerWithPlayerItem:playerItem];
self.player.allowsExternalPlayback= YES;
self.avPlayerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player];
self.avPlayerLayer.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
//self.player.automaticallyWaitsToMinimizeStalling = false;
self.avPlayerLayer.videoGravity = AVLayerVideoGravityResizeAspect;
//I HAVE TRIED THIS AT DIFFERENT LAYERS
[self.view.layer insertSublayer:self.avPlayerLayer atIndex:0
];
//THIS DOES PRINT IN LOG
NSLog(#"this is getting played");
[self.player.currentItem addObserver:self
forKeyPath:#"status"
options:0
context:nil];
}
-(IBAction)showVideo:(id)sender;{
[self startplayer];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if (object == self.player.currentItem && [keyPath isEqualToString:#"status"])
{
NSLog(#"This is being called");
[self.player play];
self.player.rate = 1.0;
if (self.player.currentItem.status == AVPlayerStatusReadyToPlay)
{
//THIS IS ALSO BEING PRINTED IN LOG
NSLog(#"This is being called");
[self.player play];
self.player.rate = 1.0;
}
}
}
#end
Even though when I press the button to showVideo and the log show all parts are activated, no screen shows up. Does anyone have any ideas why this is happening?
I have figured out that the camera is sending out a steam of mjpeg images that work in the video player in Blynk but apparently Apple doesn't use. I think this is the problem in that the player can't recognize or decode the format so no image nothing.
Does anyone have an idea of how to play an mjpeg image streams
So I couldn't get the video to stream using AVPlayer, but by creating a WKWebView and opening the server in it I got the live video to play. Only thing is getting it to resize bigger one can see the details better. But at least it works. Here is the code.
#import <WebKit/WKWebViewConfiguration.h>
WKWebViewConfiguration *theConfiguration = [[WKWebViewConfiguration alloc] init];
self.webView = [[WKWebView alloc] initWithFrame:CGRectMake(self.view.center.x-(320/2),self.view.center.y-(240/2), 320, 240) configuration:theConfiguration];
NSURL *nsurl=[NSURL URLWithString:#"http://70.176.81.136:81/CFC878/1"];
NSURLRequest *nsrequest=[NSURLRequest requestWithURL:nsurl];
[_webView loadRequest:nsrequest];
[self.view insertSubview:self.webView atIndex:14];
I've noticed that AVPlayerItemDidPlayToEndTimeNotification is occasionally sent when the network is deactivated and the video cannot continue playing. This is despite the video not having completed.
This can be reproduced with the following code:
#import "ViewController.h"
#import
#interface ViewController ()
#property AVPlayerItem *item;
#property AVPlayer *player;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSURL *url = [NSURL URLWithString:#"https://video-dev.github.io/streams/x36xhzz/x36xhzz.m3u8"];
self.item = [[AVPlayerItem alloc] initWithURL: url];
self.player = [[AVPlayer alloc] initWithPlayerItem:self.item];
AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player];
playerLayer.frame = self.view.bounds;
[NSNotificationCenter.defaultCenter addObserver:self selector:#selector(handleNotification:) name:AVPlayerItemDidPlayToEndTimeNotification object:self.item];
[self.view.layer addSublayer:playerLayer];
[self.player addObserver:self forKeyPath:#"status" options:0 context:nil];
[[AVAudioSession sharedInstance]
setCategory: AVAudioSessionCategoryPlayback
error: nil];
[self.player play];
NSLog(#"Playing");
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
change:(NSDictionary *)change context:(void *)context {
if (object == self.player && [keyPath isEqualToString:#"status"]) {
}
}
-(void)handleNotification:(NSNotification*)notification {
NSLog(#"%#", notification.name.debugDescription);
NSLog(#"HandleNotification called at:%lld seconds. Duration on player is:%lld seconds", self.player.currentTime.value/self.player.currentTime.timescale, self.item.duration.value/self.item.duration.timescale);
}
#end
Reproduction steps are:
1. Run the app and let the video play for around 40s.
2. Kill the network on the device.
AVPlayerItemDidPlayToEndTimeNotification is fired and written to the log.
Is there any reason why I should expect this to happen? And if so, how can I distinguish between an end of play event and a failure to continue playback due to lack of buffered content?
I found same issue from AVPlayer's notification.
When AVPlayerItemFailedToPlayToEndTime is trigged, I check AVPlayerItem's position from the end.
Code sample from ModernAVPlayer library:
I am trying to play video with new AVPlayerViewController introduced in XCode 6.
To play video i have done this setup.
Using local mp4 file to play video
Extended AVPlayerViewController
Player setup code :
-(void)setupPlayer
{
NSString* filePath = [[NSBundle mainBundle] pathForResource:#"exodus_trailer" ofType:#"mp4"];
NSLog(#"File Path : %#",filePath);
AVAsset *avAsset = [AVAsset assetWithURL:[NSURL URLWithString:filePath]];
AVPlayerItem *avPlayerItem =[[AVPlayerItem alloc]initWithAsset:avAsset];
self.player = [[AVPlayer alloc]initWithPlayerItem:avPlayerItem];
[self.player addObserver:self forKeyPath:#"status" options:0 context:nil];
[self.player play];
}
KVO handling :
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if (object == self.player && [keyPath isEqualToString:#"status"])
{
if (self.player.status == AVPlayerStatusFailed)
{
NSLog(#"AVPlayer Failed");
}
else if (self.player.status == AVPlayerStatusReadyToPlay)
{
NSLog(#"AVPlayerStatusReadyToPlay");
[self.player play];
}
else if (self.player.status == AVPlayerItemStatusUnknown)
{
NSLog(#"AVPlayer Unknown");
}
}
}
Issue :
KVO log is printing AVPlayerStatusReadyToPlay and file path seems ok. Previously view was at least showing player with all default controls, but now without any changes it started to show Quick time logo without any control. What is meaning of showing this logo ? what i am doing wrong here ?
Screenshot :
Here is exactly like what you wanted to do. The problem with your code is that you are not using file path, use this to load the file path NSURL *url = [NSURL fileURLWithPath:urlString]
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *urlString = [[NSBundle mainBundle] pathForResource:#"testfile" ofType:#"mp4"];
NSURL *url = [NSURL fileURLWithPath:urlString];
self.player = [[AVPlayer alloc] initWithURL:url];
[self.player addObserver:self forKeyPath:#"status"
options:NSKeyValueObservingOptionNew
context:NULL];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if (object == self.player) {
AVPlayerStatus status = [change[NSKeyValueChangeNewKey] integerValue];
if (status == AVPlayerStatusReadyToPlay) {
[self.player play];
[self.player removeObserver:self forKeyPath:#"status"];
}
}
else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
#end
I am using avplayer for play audio url, but it is not working, I don't know where i am wrong
NSString *radioURL = #"https://www.example.com";
radioPlayer = [AVPlayer playerWithURL:[NSURL URLWithString:radioURL]] ;
// [radioPlayer seekToTime:kCMTimeZero];
NSLog(#"radio player %#",radioPlayer.currentItem);
[radioPlayer play];
Any help would be appreciated.
I strongly recommended the code below to play radio streaming: please take a look also AVPlayer_Class
-(void)Play{
NSString *radioURL = #"https://www.example.com"; //this url must valid
AVPlayer *player = [[AVPlayer alloc]initWithURL:[NSURL URLWithString:radioURL]];
self.songPlayer = player; //self.songPlayer is a globle object of avplayer
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(playerItemDidReachEnd:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:[songPlayer currentItem]];
[self.songPlayer addObserver:self forKeyPath:#"status" options:0 context:nil];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if (object == songPlayer && [keyPath isEqualToString:#"status"]) {
if (songPlayer.status == AVPlayerStatusFailed) {
NSLog(#"AVPlayer Failed");
} else if (songPlayer.status == AVPlayerStatusReadyToPlay) {
NSLog(#"AVPlayerStatusReadyToPlay");
[self.songPlayer play];
} else if (songPlayer.status == AVPlayerItemStatusUnknown) {
NSLog(#"AVPlayer Unknown");
}
}
}
- (void)playerItemDidReachEnd:(NSNotification *)notification {
// code here to play next sound file
}
Ref link is - Streaming mp3 audio with AVPlayer
I had the same issue and just realized that I wasn't retaining the player (using ARC)! So it gets deallocated and stop playing immediately after start.
You need to make sure that you have a strong property radioPlayer and use self.radioPlayer instead of radioPlayer.
You are doing good but your method need to correct on one place.Check using the below method:
NSURL *audioURL = [NSURL URLWithString:radioURL];
NSData *audioData = [NSData dataWithContentsOfURL:audioURL];
self.audioPlayer = [[AVAudioPlayer alloc] initWithData:audioData error:nil];
self.audioPlayer.numberOfLoops = -1;
self.audioPlayer.delegate = self;
[self.audioPlayer prepareToPlay];
self.audioPlayer.volume=1.0;
[self.audioPlayer autorelease];
[self.audioPlayer Play];
and add proper delegate methods for AVAudioPlayer.
Make Sure URL is AddingPercentEscapes.
NSURL *audioURL = // Your Url;
NSString *encodedString = [#"Your Url" stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *myURL = [[NSURL alloc] initWithString:encodedString]
AVPlayer *player = [AVPlayer playerWithURL:myURL];
[player prepareToPlay];
player play];
Did you forgot to set the attribute App Transport Security Settings -> Allow Arbitrary Loads (Yes)?
So I am building a custom video player using AVFoundation - AVPlayer and AVPlayerLayer.
Currently, all I want the player to do is play a video in the asset library with a hardcoded url to that video. I would like this to be contained in a SubClass of UIView so I can use it all around my app.
Here is my code so far:
CUPlayer.h:
#interface CUPlayer : UIView
{
AVPlayer *player;
AVPlayerLayer *playerLayer;
AVPlayerItem *item;
NSURL *url;
}
#property(nonatomic) UIViewAutoresizing autoresizingMask;
#end
CUPlayer.m:
#implementation CUPlayer
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
// Initialization code
self.backgroundColor = [UIColor redColor];
[self setupURL];
}
return self;
}
-(void)setupURL
{
NSLog(#"URL setting up");
NSString *string = #"assets-library://asset/asset.mov?id=0A937F0D-6265-452D-8800- 1A760E8E88B9&ext=mov";
url = [[NSURL alloc] initFileURLWithPath: string];
[self setupPlayerForURL];
}
-(void)setupPlayerForURL
{
AVAsset *asset = [AVURLAsset URLAssetWithURL:url options:nil];
item = [AVPlayerItem playerItemWithAsset:asset];
player = [AVPlayer playerWithPlayerItem:item];
[player addObserver:self forKeyPath:#"status" options:0 context:nil];
playerLayer = [AVPlayerLayer playerLayerWithPlayer:player];
//player.actionAtItemEnd = AVPlayerActionAtItemEndNone;
[self.layer addSublayer:playerLayer];
playerLayer.frame = CGRectMake(0, 0, 200, 200);
//[playerLayer setBackgroundColor:[UIColor greenColor].CGColor];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if (object == player && [keyPath isEqualToString:#"status"]) {
if (player.status == AVPlayerStatusFailed) {
NSLog(#"AVPlayer Failed");
} else if (player.status == AVPlayerStatusReadyToPlay) {
NSLog(#"AVPlayer Ready to Play");
[player play];
} else if (player.status == AVPlayerItemStatusUnknown) {
NSLog(#"AVPlayer Unknown");
}
}
}
And then I am calling this from the View Controller:
CUPlayer *cuPlayer = [[CUPlayer alloc]initWithFrame:CGRectMake(0, 0, 250, 250)];
[self.view addSubview:cuPlayer];
This complies but just give me a red square without the video playing. The URL to the local file is definitely correct. I can get it working if I hold all the code in the view controller and run the play in -(void)viewDidLayoutSubviews.
Help would very much be appreciated, I have read all the documentation multiple times trying to work this thing out.
Tom