i've been using an html string for a long period for playing youtube videos through an UIWebView, the problem is i want to get notifications with playbackstate changed. i've decided to create an MPMoviePlayerController and play the youtube video through this, but cant seem to make it work. i'm using following code in viewdidload:
NSString *urlAddress = #"http://www.youtube.com/watch?v=m01MYOpbdIk";
NSURL *url = [NSURL URLWithString:urlAddress];
CGFloat width = [UIScreen mainScreen].bounds.size.width;
CGFloat height = [UIScreen mainScreen].bounds.size.height;
movie = [[MPMoviePlayerController alloc] initWithContentURL:url];
movie.scalingMode=MPMovieScalingModeAspectFill;
movie.view.frame = CGRectMake(0.0, 0.0, width, height);
[self.view addSubview:movie.view];
[movie play];
Gives me this error:
_itemFailedToPlayToEnd: {
kind = 1;
new = 2;
old = 0;
}
For me this library did work perfectly! https://github.com/hellozimi/HCYoutubeParser
moviePlayer = [[MPMoviePlayerController alloc] init];
moviePlayer.shouldAutoplay = YES;
moviePlayer.fullscreen = YES;
moviePlayer.repeatMode = MPMovieRepeatModeNone;
moviePlayer.controlStyle = MPMovieControlStyleDefault;
moviePlayer.movieSourceType = MPMovieSourceTypeFile;
moviePlayer.scalingMode = MPMovieScalingModeAspectFit;
After this call method.
[self callYouTubeURL:[NSString stringWithFormat:#"http://www.youtube.com/embed/%#",_urlcode]];
In this method parse youtube link.
- (void)callYouTubeURL:(NSString *)urlLink
{
NSURL *url = [NSURL URLWithString:urlLink];
actvity.hidden = NO;
[HCYoutubeParser thumbnailForYoutubeURL:url thumbnailSize:YouTubeThumbnailDefaultHighQuality completeBlock:^(UIImage *image, NSError *error) {
if (!error) {
[HCYoutubeParser h264videosWithYoutubeURL:url completeBlock:^(NSDictionary *videoDictionary, NSError *error) {
NSDictionary *qualities = videoDictionary;
NSString *URLString = nil;
if ([qualities objectForKey:#"small"] != nil) {
URLString = [qualities objectForKey:#"small"];
}
else if ([qualities objectForKey:#"live"] != nil) {
URLString = [qualities objectForKey:#"live"];
}
else {
[[[UIAlertView alloc] initWithTitle:#"Error" message:#"Couldn't find youtube video" delegate:nil cancelButtonTitle:#"Close" otherButtonTitles: nil] show];
return;
}
_urlToLoad = [NSURL URLWithString:URLString];
[self urlLoadintoPlayer];
}];
}
else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:[error localizedDescription] delegate:nil cancelButtonTitle:#"Dismiss" otherButtonTitles:nil];
[alert show];
}
}];
}
After this load newly parse url into player.
-(void)urlLoadintoPlayer
{
moviePlayer.contentURL = _urlToLoad;
}
Make use of custom LBYouTubePlayerViewController
It is a subclass of MPMoviePlayerViewController.
LBYouTubeView is just a small view that is able to display YouTube videos in a MPMoviePlayerController. You even have the choice between high-quality and standard quality stream.
It just loads the HTML code of YouTube's mobile website and looks for the data in the script tag.
LBYouTubeView doesn't use UIWebView which makes it faster and look cleaner.
Official way to play youtube videos: 1) UIWebView with the embed tag from Youtube the UIWebView's content.2) Using youtube-ios-player-helper[Google official way]
Unfortunately, there's no way to directly play a youtube video with MPMoviePlayerController because youtube does not expose direct links to the video files.
There are library which runs youtube videos through MPMoviePlayerController, but they are against the TOC of youtube. Hence simplest method is to go for youtube-ios-player-helper.
In case youtube-ios-player-helper pod doesn't work you can add YTPlayer.h/.m and assets folder to your project and write a bridge header with #import "YTPlayerView.h" and rest procedure you can follow on https://github.com/youtube/youtube-ios-player-helper
This definitely worked for me!
Related
I'm trying to use SFSpeechRecognizer but I don't have a way to test if I'm implementing it correctly, and since its a relatively new class i couldn't find a sample code (I don't know swift). Am I making any unforgivable mistakes/missing something ?
[SFSpeechRecognizer requestAuthorization:^(SFSpeechRecognizerAuthorizationStatus status){
if (status == SFSpeechRecognizerAuthorizationStatusAuthorized) {
SFSpeechRecognizer* recognizer = [[SFSpeechRecognizer alloc] init];
recognizer.delegate = self;
SFSpeechAudioBufferRecognitionRequest* request = [[SFSpeechAudioBufferRecognitionRequest alloc] init];
request.contextualStrings = #[#"data", #"bank", #"databank"];
SFSpeechRecognitionTask* task = [recognizer recognitionTaskWithRequest:request resultHandler:^(SFSpeechRecognitionResult* result, NSError* error){
SFTranscription* transcript = result.bestTranscription;
NSLog(#"%#", transcript);
}];
}
}];
I´m trying too but this code works for me, after all SFSpeechRecognizer and SFSpeechAudioBufferRecognitionRequest are not the same, so I think (haven´t tested) you have to ask for different permissions (have you asked for permissions before? to use the microphone and the speechRecognition?). Ok here´s the code:
//Available over iOS 10, only for maximum 1 minute, need internet connection; can be sourced from an audio recorded file or over the microphone
NSLocale *local =[[NSLocale alloc] initWithLocaleIdentifier:#"es-MX"];
speechRecognizer = [[SFSpeechRecognizer alloc] initWithLocale:local];
NSString *soundFilePath = [myDir stringByAppendingPathComponent:#"/sound.m4a"];
NSURL *url = [[NSURL alloc] initFileURLWithPath:soundFilePath];
if(!speechRecognizer.isAvailable)
NSLog(#"speechRecognizer is not available, maybe it has no internet connection");
SFSpeechURLRecognitionRequest *urlRequest = [[SFSpeechURLRecognitionRequest alloc] initWithURL:url];
urlRequest.shouldReportPartialResults = YES; // YES if animate writting
[speechRecognizer recognitionTaskWithRequest: urlRequest resultHandler: ^(SFSpeechRecognitionResult * _Nullable result, NSError * _Nullable error)
{
NSString *transcriptText = result.bestTranscription.formattedString;
if(!error)
{
NSLog(#"transcriptText");
}
}];
I need your help in feeding image/video on my app. I am using AVPlayer for displaying videos.
I am facing problem in displaying images once video is displayed, the previous videos are displaying on the upcoming images.
Here is my code. The image Url in userPostImageStr is correct but still it is showing last video.
if (userPostVideo != (NSString *)[NSNull null])
{
AVPlayerViewController *playerViewController = [[AVPlayerViewController alloc] init];
AVPlayer *player = [[AVPlayer alloc] init];
NSURL *url = [NSURL URLWithString:userPostVideo];
AVURLAsset *asset = [AVURLAsset assetWithURL:url];
AVPlayerItem *item = [AVPlayerItem playerItemWithAsset:asset];
player = [[AVPlayer alloc] initWithPlayerItem:item];
playerViewController.player = player;
[playerViewController.view setFrame:cell.userPostImage.frame];
playerViewController.showsPlaybackControls = NO;
[cell.userPostImage addSubview:playerViewController.view];
[player play];
}
else if (userPostImageStr != (NSString *)[NSNull null])
{
if (userPostImageStr != (NSString *)[NSNull null])
{
[cell.userPostImage setShowActivityIndicatorView:YES];
[cell.userPostImage setIndicatorStyle:UIActivityIndicatorViewStyleGray];
[cell.userPostImage sd_setImageWithURL:[NSURL URLWithString:userPostImageStr]
placeholderImage:[UIImage imageNamed:#"appIcon"] options: SDWebImageRefreshCached
completed:^(UIImage image, NSError error, SDImageCacheType cacheType, NSURL *imageURL)
{
if (image.size.width < cell.contentView.frame.size.width)
{
// NEED to write the for contraint update at runtime
//[postImageView setConstraintConstant:image.size.width forAttribute:NSLayoutAttributeWidth];
}
}];
}
}
else
{
cell.userPostImage.image = [UIImage imageNamed:#"appIcon"];
}
Please reply if anybody aware of this problem.
Thank you.
The problem is that you are adding a subview containing the player to the cell without ever removing the subview. That's what's happening when you call
[cell.userPostImage addSubview:playerViewController.view];
When the cell gets reused, the views that have been added previously are still there and causing all sorts of unexpected behavior.
Before you add a subview, you should remove the existing view by calling
[theViewToBeRemoved removeFromSuperView];
This requires you to keep a reference to the view. One way is by setting the tag on the view. For example:
// Set the tag on the view.
playerViewController.view.tag = 1000;
// Remove the view with the matching tag.
[[cell.userPostImage viewWithTag:1000] removeFromSuperView];
I would also recommend having the player be a property in your cell subclass to keep everything organized.
I am having some trouble in sharing videos with airdrop. So, i am using the AssetLibrary like this :
else if (conformsToVideo) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Asset Loaded" message:#"Video One Loaded"
delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
self.mediaAsset = [AVAsset assetWithURL:[info objectForKey:UIImagePickerControllerMediaURL]];
UIActivityViewController * controller = [[UIActivityViewController alloc] initWithActivityItems:#[self.mediaAsset] applicationActivities:nil];
[self presentViewController:controller animated:YES completion:nil];
}
Maybe this is just not the way to do it, I don't know and I didn't find any tutorial about it so if you have one, I will gladly take it.
Now my problem is that when i select a video everything works fine until the UIActivityViewController pops out , i don't have any error but I can't use airdrop (nor any other service BTW) the only thing I can do is press the Cancel button of the UIAVController.
I am using iOS 8.3.
Thanks for your help
Ok, eventually I found an answer, maybe not the best but I put it there in case it helps someone cause I didn't find much on sharing video with airdrop :
NSURL * path = [info objectForKey:UIImagePickerControllerReferenceURL];
BOOL conformsToVideo = (UTTypeConformsTo((__bridge_retained CFStringRef) mediaType, kUTTypeAudiovisualContent));
if (conformsToVideo) {
[self.library assetForURL:path
resultBlock:^(ALAsset *asset) {
ALAssetRepresentation* assetRepresentation = [asset defaultRepresentation];
NSString* outputDirectory = [NSString stringWithFormat:#"%#", NSTemporaryDirectory()];
NSString* pathToCopy = [outputDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#", assetRepresentation.filename]];
NSUInteger size = (NSUInteger)assetRepresentation.size;
NSMutableData* data = [NSMutableData dataWithLength:size];
NSUInteger bytesRead = [assetRepresentation getBytes:data.mutableBytes fromOffset:0 length:size error:nil];
NSURL * url = nil;
if ([data writeToFile:pathToCopy atomically:YES])
{
NSLog(#"Ok");
url = [NSURL fileURLWithPath:pathToCopy];
UIActivityViewController * controller = [[UIActivityViewController alloc] initWithActivityItems:#[url] applicationActivities:nil];
[self presentViewController:controller animated:YES completion:nil];
}
} failureBlock:^(NSError *error) {
NSLog(#"Failure to use the ALAsset");
}
];
}
I found the solution using this question : Share a video from asset library with AirDrop fails
I am merely adding the previous steps to the code given there, hope it can be useful.
When I read videos in my iOS application which it uses the Google Drive API, at a certain time of reading a video, I have this error : Error Domain=com.google.HTTPStatus Code=403 "(null)"
And I can read the other videos until a certain amount of times, when I still have this error.
Here is my code :
if ([file.mimeType isEqualToString:#"video/quicktime"])
{
GTMHTTPFetcher *fetcher = [service.fetcherService fetcherWithURLString:file.downloadUrl];
[fetcher beginFetchWithCompletionHandler:^(NSData *data, NSError *error) {
if (error == nil) {
NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
NSString* accessToken = [userDefaults objectForKey:#"accessToken"];
player = [[MPMoviePlayerController alloc]initWithContentURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#&access_token=%#",file.downloadUrl,accessToken]]];
[[player view] setFrame:CGRectMake(self.view.frame.size.width/2-150, self.navigationController.navigationBar.frame.size.height+30, 300, 400)];
player.contentURL = [NSURL URLWithString:[NSString stringWithFormat:#"%#&access_token=%#",file.downloadUrl,accessToken]];
[player setContentURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#&access_token=%#",file.downloadUrl,accessToken]]];
[player setMovieSourceType:MPMovieSourceTypeFile];
player.scalingMode = MPMovieScalingModeNone;
player.controlStyle = MPMovieControlStyleDefault;
player.backgroundView.backgroundColor = [UIColor whiteColor];
player.repeatMode = MPMovieRepeatModeNone;
[self.view addSubview: [player view]];
[player play];
} else {
NSLog(#"An error occurred: %#", error);
}
}];
}
Is it a cause of the amount of data downloaded ? Did I forget anything to enable or disable ?
I don't use GTMHTTPFetcher but If your problem is about HTTPStatus Code=403 , it's forbidden to access the service. So you can't do anything in this case. You should show a message to user when they try to reach forbidden video.
You can check the statusCode
if(HTTPStatusCode == 403){
//Show an alertView to user
}
or you should control video which has permissions. Otherwise your app will crash.
More info about HTTP status code 403
Checking other status code will clear your application.
Status are so important to fetch data. If something went wrong you should check it.
I am trying to parse youtube link and play on MPMoviePlayerViewController.
I am just following this link and I can parse successfully with their example youtube link. https://github.com/hellozimi/HCYoutubeParser
http://www.youtube.com/watch?v=8To-6VIJZRE
However, the problem is that I can't parse other youtube URL like this
http://www.youtube.com/watch?v=Ndy1J859n5I
Is it because of video duration? I would like to know how to solve this.
Code
// Gets an dictionary with each available youtube url
NSDictionary *videos = [HCYoutubeParser h264videosWithYoutubeURL:[NSURL URLWithString:#"http://www.youtube.com/watch?v=8To-6VIJZRE"]];
// Presents a MoviePlayerController with the youtube quality medium
MPMoviePlayerViewController *mp = [[[MPMoviePlayerViewController alloc] initWithContentURL:[NSURL URLWithString:[videos objectForKey:#"medium"]]] autorelease];
[self presentModalViewController:mp animated:YES];
// To get a thumbnail for an image there is now a async method for that
[HCYoutubeParser thumbnailForYoutubeURL:url
thumbnailSize:YouTubeThumbnailDefaultHighQuality
completeBlock:^(UIImage *image, NSError *error) {
if (!error) {
self.thumbailImageView.image = image;
}
else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:[error localizedDescription] delegate:nil cancelButtonTitle:#"Dismiss" otherButtonTitles:nil];
[alert show];
}
}];
I have managed to successfully send videos from a class in Parse.com to an app. Is this what you are trying to do? If so, the above code is completely incorrect.