How to play youtube video using URL in AVPlayer IOS? - ios

I want to load video in AVPlayer using YouTube URL but it is not showing anything.Whenever i am loading from a local storage using NSBundle it is working fine.Is there is any alternative to load video or we can do something in AVPlayer.
This is my code:
- (void)viewDidLoad
{
[super viewDidLoad];
NSError *setCategoryError = nil;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error: &setCategoryError];
AVAsset *asset = [AVAsset assetWithURL:[NSURL fileURLWithPath:#"http://www.youtube.com/watch?v=zPP6lXaL7KA&feature=youtube_gdata_player"]];
avPlayerItem = [[AVPlayerItem alloc]initWithAsset:asset];
self.songPlayer = [AVPlayer playerWithPlayerItem:avPlayerItem];
self.avPlayerLayer = [AVPlayerLayer playerLayerWithPlayer: self.songPlayer];
self.avPlayerLayer.frame = self.view.layer.bounds;
UIView *newView = [[UIView alloc] initWithFrame:self.view.bounds];
[newView.layer addSublayer:avPlayerLayer];
[self.view addSubview:newView];
[ self.songPlayer play];
}

You should use the iOS Youtube Helper library for playing youtube videos.
https://developers.google.com/youtube/v3/guides/ios_youtube_helper
I don't know if you can use the AVPlayer. I've seen some examples using MPMoviePlayerController on CocoaControls, like this one: https://www.cocoacontrols.com/controls/hcyoutubeparser or this one: https://www.cocoacontrols.com/controls/xcdyoutubevideoplayerviewcontroller
But I don't think using youtube's url directly in your player fits the ToS of the platform. So I will recommend you tu use the Youtube Helper Library if you are planning to publish your app.

Use XCDYouTubeKit pod
Get youtube video id from url like https://www.youtube.com/watch?v=dLEATulyCdw
you can use this code:
extension URL {
func youtubeVideoId() -> String? {
let pattern = #"(?<=(youtu\.be\/)|(v=)).+?(?=\?|\&|$)"#
let testString = absoluteString
if let matchRange = testString.range(of: pattern, options: .regularExpression) {
let subStr = testString[matchRange]
return String(subStr)
} else {
return .none
}
} }
Then call XCDYouTubeClient.default().getVideoWithIdentifier(videoId)
In the completion you can get url. video?.streamURLs contains urls with a different quality, choose desired.
Finally just pass this url to AVPlayer...
Update
Visual explanation
Use first instead of youtubeMaxAvailableQuality

I don't think if you can use this now because i just used this and encountered the same case.
I read the apple document-,it definitely refers to that (You cannot directly create an AVAsset instance to represent the media in an HTTP Live Stream.).
Instead here is apple's example:
NSURL *url = [NSURL URLWithString:#"<#Live stream URL#>];
// You may find a test stream at
http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8.
self.playerItem = [AVPlayerItem playerItemWithURL:url];
see,if not local url,should be playerItemWithURL:^_^

Related

could not load URL AVPlayer not playing video

*Below two lines are for those who wants to use AVPlayer in their app.
This player works fine if i uncomment middle line in comments i.e NSURL *url and set the first line below comments i.e playerWithUrl:url , and comment the starting two lines.
*Below is My Real Problem, I need Help.
But i am not able to set URL the value to the player method-playerWithURL which is a first line below comments, and i am setting it through fileURL instance which i have created at starting in 2 line. IN the debugger it shows API path in *localfilepath. but when i am setting local file path to player through fileURL it shows nil.
But if i use middle line in comments i.e set *url for player everything works fine.
Help me to convert API into URL for that player property
NSString *localfilepath=[NSString stringWithFormat:#"%#",[managedObject valueForKey:#"clip_path"]];
NSURL *fileURL=[NSURL fileURLWithPath:localfilepath]; //because of this i am getting video URL but something #"file://" gets attached to it in the end thus not playing video URL because of that fileURLWithPath suggest something another way to fetch URL
// videoAVURLAsset = [AVURLAsset assetWithURL:fileURL];
// NSURL *url = [[NSURL alloc] initWithString:#"http://www.example.com/example_clips/SHAINA%20NC%20NEWS%20X%20180516%201657PM.mp4"];
// created player here //
player = [AVPlayer playerWithURL:fileURL]; //here i want to set the value which is in the *localfileurl
AVPlayerViewController *controller = [[AVPlayerViewController alloc] init];
[self addChildViewController:controller];
[self.view addSubview:controller.view];
controller.view.frame = CGRectMake(10,80,300,300);
controller.player = player;
controller.showsPlaybackControls = YES;
[player pause];
[player play];
You should be using [NSURL fileURLWithPath:] to generate the URL object from a local file path string:
NSURL *fileURL = [NSURL fileURLWithPath:localfilepath];
Here is how I play a video in iOS:
First create a web view
Then link it to your view controller code
and then add this in the viewdidload()
//add the video to the player
let myYoutubeVideo = "https://www.youtube.com/embed/YNUEAxUGxyE"
let myHTMLString = "<iframe width=\"\(videoPlayer.frame.width)\" height=\"\(videoPlayer.frame.height)\" src=\"\(myYoutubeVideo)?&playsinline=1\" frameborder=\"0\" allowfullscreen></iframe>"
videoPlayer.allowsInlineMediaPlayback = true
videoPlayer.loadHTMLString(myHTMLString, baseURL: nil)
videoPlayer.frame = UIScreen.mainScreen().bounds
videoPlayer.center = self.view.center
videoPlayer.backgroundColor = UIColor.clearColor()
Try putting the file in this directory
#if TARGET_IPHONE_SIMULATOR
// where are you?
NSLog(#"Documents Directory: %#", [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]);
#endif
This is the Documents directory for your app in the simulator. Then try to run it from there.
That way it should act like its pulling off the phone and not your local pc.
And give this a try too
file:///Users/codercat/Library/Developer/CoreSimulator/Devices/YourProjectDict/data/Containers/Data/Application/(sample digit)7F53CFB3-C534-443F-B595-62619BA808F2/Documents/your file located here
This one is for Xcode 7 and higher
i have made it guys :) i found the answer :) this is a complete solution if you have many video URL's and you want to play videos from server directly in your player so you need to fetch all your clip paths properly first and use the following code
// here i am fetching all the url downloaded from server using core data managed objects
NSString *localfilepath=[NSString stringWithFormat:#"%#",[managedObject valueForKey:#"clip_path"]];
// then on below line i am encoding it into NSUTF8StringEncoding format
don't forget to do this otherwise video will not play as it wasn't in my case
NSURL *url = [NSURL URLWithString:[localfilepath stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
// and below i have assigned url to the player and created the player
player = [AVPlayer playerWithURL:url];
AVPlayerViewController *controller = [[AVPlayerViewController alloc] init];
[self addChildViewController:controller];
[self.view addSubview:controller.view];
controller.view.frame = CGRectMake(10,80,300,300);
controller.player = player;
controller.showsPlaybackControls = YES;
//player.closedCaptionDisplayEnabled = NO;
[player pause];
[player play];

How to play YouTube content on tvOS

How would one play a YouTube video on Apple tvOS?
YouTube's embed feature works in iOS 9 as the OS has a UIWebView we can embed it into.
The new tvOS does not include a UIWebView so I cannot see a way to embed the YouTube video.
UIWebView and MPMoviePlayerController are not available for tvOS. Our next option is to use AVPlayer to play YouTube videos.
AVPlayer cannot play a YouTube video from a standard YouTube URL, ie. https://www.youtube.com/watch?v=8To-6VIJZRE. It needs a direct URL to the video file. Using HCYoutubeParser we can accomplish exactly that. Once we have the URL we need, we can play it with our AVPlayer like so:
NSString *youTubeString = #"https://www.youtube.com/watch?v=8To-6VIJZRE";
NSDictionary *videos = [HCYoutubeParser h264videosWithYoutubeURL:[NSURL URLWithString:youTubeString]];
NSString *urlString = [NSString stringWithFormat:#"%#", [videos objectForKey:#"medium"]];
AVAsset *asset = [AVAsset assetWithURL:[NSURL URLWithString:urlString]];
AVPlayerItem *avPlayerItem = [[AVPlayerItem alloc]initWithAsset:asset];
AVPlayer *videoPlayer = [AVPlayer playerWithPlayerItem:avPlayerItem];
AVPlayerLayer *avPlayerLayer = [AVPlayerLayer playerLayerWithPlayer:videoPlayer];
avPlayerLayer.frame = playerView.layer.bounds;
[playerView.layer addSublayer:avPlayerLayer];
[videoPlayer play];
Note that this is NOT allowed under YouTube's TOS. Use it at your own risk. Your app may stop working at any point if YouTube notices you are not following the TOS or if YouTube changes the embed code it generates.
Swift 2.0 version of Daniel Storm's answer:
let youTubeString : String = "https://www.youtube.com/watch?v=8To-6VIJZRE"
let videos : NSDictionary = HCYoutubeParser.h264videosWithYoutubeURL(NSURL(string: youTubeString))
let urlString : String = videos["medium"] as! String
let asset = AVAsset(URL: NSURL(string: urlString)!)
let avPlayerItem = AVPlayerItem(asset:asset)
let avPlayer = AVPlayer(playerItem: avPlayerItem)
let avPlayerLayer = AVPlayerLayer(player: avPlayer)
avPlayerLayer.frame = CGRectMake(0, 0, self.view.frame.width, self.view.frame.height);
self.view.layer.addSublayer(avPlayerLayer)
avPlayer.play()
XCDYouTubeKit has been a popular way to directly play a YouTube video on iOS for a while, and the developer recently updated it to support the new AppleTV.
Here's the code from the Objective-C example:
AVPlayerViewController *playerViewController = [AVPlayerViewController new];
[self presentViewController:playerViewController animated:YES completion:nil];
__weak AVPlayerViewController *weakPlayerViewController = playerViewController;
[[XCDYouTubeClient defaultClient] getVideoWithIdentifier:playlistItem.snippet.resourceId.videoId completionHandler:^(XCDYouTubeVideo * _Nullable video, NSError * _Nullable error) {
if (video)
{
NSDictionary *streamURLs = video.streamURLs;
NSURL *streamURL = streamURLs[XCDYouTubeVideoQualityHTTPLiveStreaming] ?: streamURLs[#(XCDYouTubeVideoQualityHD720)] ?: streamURLs[#(XCDYouTubeVideoQualityMedium360)] ?: streamURLs[#(XCDYouTubeVideoQualitySmall240)];
weakPlayerViewController.player = [AVPlayer playerWithURL:streamURL];
[weakPlayerViewController.player play];
}
else
{
[self dismissViewControllerAnimated:YES completion:nil];
}
}];
Swift example here.
Sadly, even an Apple Staff person echoed the “negative” on this. From an Apple Developer Forums thread on the topic:
There is no support for WebViews on tvOS, and so an iframe implementation will not work. TVML does not offer this capability.
After some trying I'm happy to announce that:
youtube://watch/video_id
will open the YouTube app and play the YouTube video.
Enjoy.
As an addition to Daniel Storm's answer, you can also achieve this with the new TVML language using the code:
<lockup videoURL="http://mp4-url.mp4">
<img src="video thumbnail.jpg" />
</lockup>
(for this to work you'll need the direct video file (mp4) which also is not allowed by the Youtube TOS)
EDIT, found also the .JS solution:
How do I play a video on tvOS for Apple TV?
I used this one https://cocoapods.org/pods/youtube-parser
Youtube.h264videosWithYoutubeURL(testURL) { (videoInfo, error) -> Void in
if let videoURLString = videoInfo?["url"] as? String,
videoTitle = videoInfo?["title"] as? String {
print("\(videoTitle)")
print("\(videoURLString)")
self.playVideo(videoURLString)
}
}

I'm trying to stream the following url in ios but it won't play

the audio i want to stream is:http://streamer2.ultapulta.com:8001
I've tried other streaming links and they work in my code.
NSURL *url = [NSURL URLWithString:streamUrl];
_myItem = [AVPlayerItem playerItemWithURL:url];
_mySound = [AVPlayer playerWithPlayerItem:_myItem];
[_mySound play]
I believe the stream is in AAC format. What should I do
You could try to use StreamingKit
Example like in documentation:
STKAudioPlayer* audioPlayer = [[STKAudioPlayer alloc] init];
[audioPlayer queue:#"http://streamer2.ultapulta.com:8001"];
And it's better to have audioPlayer as class property.

Load two AVPlayers with one video

I have two different views that are meant to play the same video, I am creating an app that will switch several times between the two views while the video is running.
I currently load the first view with the video as follows:
NSURL *url = [NSURL URLWithString:#"http://[URL TO VIDEO HERE]"];
AVURLAsset *avasset = [[AVURLAsset alloc] initWithURL:url options:nil];
AVPlayerItem *item = [[AVPlayerItem alloc] initWithAsset:avasset];
player = [[AVPlayer alloc] initWithPlayerItem:item];
playerLayer = [[AVPlayerLayer playerLayerWithPlayer:player] retain];
CGSize size = self.bounds.size;
float x = size.width/2.0-202.0;
float y = size.height/2.0 - 100;
//[player play];
playerLayer.frame = CGRectMake(x, y, 404, 200);
playerLayer.backgroundColor = [UIColor blackColor].CGColor;
[self.layer addSublayer:playerLayer];
NSString *tracksKey = #"tracks";
[avasset loadValuesAsynchronouslyForKeys:[NSArray arrayWithObject:tracksKey] completionHandler:
^{
dispatch_async(dispatch_get_main_queue(),
^{
NSError *error = nil;
AVKeyValueStatus status = [avasset statusOfValueForKey:tracksKey error:&error];
if (status == AVKeyValueStatusLoaded) {
//videoInitialized = YES;
[player play];
}
else {
// You should deal with the error appropriately.
NSLog(#"The asset's tracks were not loaded:\n%#", [error localizedDescription]);
}
});
}];
In my second view I want to load the video from the dispatch_get_main_queue so that the video in both views are in sync.
I was hoping someone could help me out with loading the data of the video from the first view into the second view.
It is very simple:
Init the first player:
AVAsset *asset = [AVAsset assetWithURL:URL];
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:asset];
AVPlayer *player = [AVPlayer playerWithPlayerItem:playerItem];
AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:player];
And the second player in the same way, BUT, use the same asset from the first one.
I have verified, it works.
There is all the info you need on the Apple page:
https://developer.apple.com/library/mac/documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/02_Playback.html
This abstraction means that you can play a given asset using different
players simultaneously
this quote is from this page.
I don't think you will be able to get this approach to work. Videos are decoded in hardware and then the graphics buffer is sent to the graphics card. What you seem to want to do is decode a video in one view but then capture the contents of the first view and show it in a second view. That will not stay in sync because it would take time to capture the contents of the first window back into main memory and then those contents would need to be sent to the video card again. Basically, that is not going to work. You also cannot decode two h.264 videos streams and expect them to be in sync.
You could implement this with another approach entirely. If you decode the h.264 video to frames on disk (save each frame as a PNG) and then write your own loop that will decode the Nth PNG in a series of PNGs and then display the results in the two different windows. That will work fast enough to be an effective implementation on newer iPhone 4 and 5 and iPad 2 and 3. If you want to make use of a more advanced implementation, take a look at my AVAnimator library for iOS, you could get this approach working in 20 minutes if you use existing code.
For this ten year old question which has only ten year old answers which are out of date, here's the up to date answer.
var leadPlayer: AVPlayer ... the lead player you want to dupe
This does not work:
let leadPlayerItem: AVPlayerItem = leadPlayer.currentItem!
yourPlayer = AVPlayer(playerItem: leadPlayerItem)
yourPlayer.play()
Apple does not allow that (try it, see error).
This works. You must use the item:
let dupeItem: AVPlayerItem = AVPlayerItem(asset: leadPlayer.currentItem!.asset)
yourPlayer = AVPlayer(playerItem: dupeItem)
yourPlayer.play()
Fortunately it's now that easy.

How can I stream audio and also be able to control volume on iOS?

I've developed an iOS app that plays two separate audio streams simultaneously. To do this I am using AVPlayer thus:
//Use URL to set up the speech radio player.
NSURL *urlStreamSpeech = [NSURL URLWithString:self.urlAddressSpeech];
playerSpeech = [AVPlayer playerWithURL:urlStreamSpeech];
//Use URL to set up the music player.
NSURL *urlStreamMusic = [NSURL URLWithString:self.urlAddressMusic];
playerMusic = [AVPlayer playerWithURL:urlStreamMusic];
I am now trying to implement a volume control so that the user will be able to control the volume for the audio streams individually. As I've tried this I have come to the conclusion that there is no volume property for the AVPlayer class. I also looked at the AVAudioPlayer class, but from what I gather that class is only able to play local audio files, not streamed audio.
So my question is: how can I control the volume of streamed audio on iOS?
NSString* resourcePath = url; //your url
NSData *_objectData = [NSData dataWithContentsOfURL:[NSURL URLWithString:resourcePath]];
NSError *error;
app.audioPlayer = [[AVAudioPlayer alloc] initWithData:_objectData error:&error];
app.audioPlayer.numberOfLoops = 0;
app.audioPlayer.volume = 1.0f;
[app.audioPlayer prepareToPlay];
if (app.audioPlayer == nil)
NSLog(#"%#", [error description]);
else
[app.audioPlayer play];
Look into the AVPlayer class, part of the AVFoundation framework... this is the objective-c (iOS) class you use for streaming audio.
look at this post Live streaming
MPMusicPlayerController* musicPlayer = [MPMusicPlayerController iPodMusicPlayer];
[musicPlayer setVolume:[SliderVolumen value]];
Only work in the device, no simulator.
Compatible with AVPlayer.

Resources