0

My code looks like this:

_player = [AVPlayer playerWithURL:destination];
_playerVC = [AVPlayerViewController new];
_playerVC.player = _player;
dispatch_async(dispatch_get_main_queue(), ^{
    [self presentViewController:_playerVC animated:YES completion:^{
        [_player play];
    }];
});

_player represents AVPlayer and _playerVC represents AVPlayerViewController. I have strong global references to these objects.

Using terminal, I played the file located at the destination (open -a quicktime\ player destinationURLAbsoluteString) and saw the file is properly loaded since it was playing.

It is a m4v file. I have played a m4a file and it properly gave me audio. I have also substituted the url I have for destination to some remote url and that worked for video. This leads me to believe it has something to do with my video. What's weird is that my AVPlayerViewController does show a black screen with all the normal controls, and even shows the video is 2 minutes and 23 seconds. Upon opening the video file manually, I can see that it is also 2 minutes and 23 seconds.

I can forward through the video properly by dragging the white dot indicative of the video's position, but I never hear anything, nor do I see anything but the black screen and controls.

TL;DR

NSLog(@"Destination: %@",destination); prints: file:///Users/MyLogin/Library/Developer/CoreSimulator/Devices/694F4C94-F785-4931-A312-4C3E7DE8673A/data/Containers/Data/Application/76C923BE-5B25-41F7-9145-63414657FDF6/Documents/mzvf_5914002519860647075.640x352.h264lc.D2.p.m4v

All in all, it looks like I'm properly retrieving the video, but for some reason my player controller is completely black and void of audio. Any help is much appreciated.

Source Code:

.m file:

#import "ViewController.h"
#import "View2ViewController.h"

#import <AVKit/AVKit.h>
#import <AVFoundation/AVFoundation.h>



@interface ViewController ()
@property NSDictionary *requestedSong;
@property (strong) AVPlayer *player;  //Declare Globally
@property (strong) AVPlayerViewController *playerVC;
@end

@implementation ViewController

- (void)viewDidLoad {
    
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor yellowColor];

    UIButton *button = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, 200, 50)];
    button.center = self.view.center;
    button.backgroundColor = [UIColor blueColor];
    [button setTitle:@"Query Songs" forState:UIControlStateNormal];
    [button addTarget:self action:@selector(buttonClicked) forControlEvents:UIControlEventTouchDown];
    [self.view addSubview:button];
    
    UIButton *button2 = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, 200, 50)];
    button2.center = CGPointMake(button.center.x, button.center.y + 200);
    button2.backgroundColor = [UIColor blueColor];
    [button2 setTitle:@"Listen to the first song" forState:UIControlStateNormal];
    [button2 addTarget:self action:@selector(button2Clicked) forControlEvents:UIControlEventTouchDown];
    [self.view addSubview:button2];

}
-(void)button2Clicked{
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[[NSOperationQueue alloc]init]];
    NSURL *url = [NSURL URLWithString:[_requestedSong objectForKey:@"previewUrl"]];
    NSMutableURLRequest *req = [[NSMutableURLRequest alloc]initWithURL:url];
    NSURLSessionDownloadTask *task = [session downloadTaskWithRequest:req];
    [task resume];
}

-(void)buttonClicked{
    
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[[NSOperationQueue alloc]init]];
    NSURL *url = [NSURL URLWithString:@"https://itunes.apple.com/search?media=movie&entity=movie&term=Mad"];
    NSMutableURLRequest *req = [[NSMutableURLRequest alloc]initWithURL:url];
    NSURLSessionDataTask *task = [session dataTaskWithRequest:req];
    [task resume];
}

-(NSURL*)localFilePathForURL:(NSURL *) previewUrl{
    //get the directory to use
    NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, true) objectAtIndex:0];
    //create the full path
    NSString *fullPath = [documentsPath stringByAppendingPathComponent:previewUrl.lastPathComponent];
    //append the filename and append to document path url
    return [NSURL fileURLWithPath:fullPath];
}

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location{
    NSURL* originalURL = downloadTask.originalRequest.URL;
    NSURL *destination = [self localFilePathForURL:originalURL];
    NSLog(@"Destination: %@",destination);
    NSFileManager *defaultFileManager = [NSFileManager defaultManager];
    if([defaultFileManager fileExistsAtPath:destination.absoluteString]){
        [defaultFileManager removeItemAtURL:destination error:nil];
    }
    
    NSError *error;

    @try {
        [defaultFileManager copyItemAtURL:location toURL:destination error:&error];
    } @catch (NSException *exception) {
        NSLog(@"copy caught with exception: %@",exception);
        return;
    }

    
    dispatch_async(dispatch_get_main_queue(), ^{
        _player = [AVPlayer playerWithURL:destination];
        _playerVC = [AVPlayerViewController new];
        _playerVC.player = _player;
        [self presentViewController:_playerVC animated:YES completion:^{
            [_player play];
        }];
        
    });
   
    
    
    NSLog(@"Hello");
}

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
    didReceiveData:(NSData *)data{
    NSError *error2;
    NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:1 error:&error2];
    _requestedSong = [[dict valueForKey:@"results"] objectAtIndex:0];
    NSLog(@"Searched: %@",[_requestedSong objectForKey:@"trackName"]);
}

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response
 completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler {
    completionHandler(NSURLSessionResponseAllow);
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

.h file:

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController <NSURLSessionDataDelegate, NSURLSessionDownloadDelegate>


@end

UPDATE:

Upon using the actual URL endpoint for mad max instead of downloading the video, it also displays a blank video. This must mean there's something weird about the format of the video or how it interacts with the AVPlayer.

Community
  • 1
  • 1
user2977578
  • 413
  • 5
  • 19
  • Have you checked the output in the console? It might be the not-so-new app transport security in IOS. You'll need to allow connections from your source as ios will block anything that's not https by default. – Daniel Ormeño Aug 23 '16 at 22:50
  • My console output is entirely my own. I allowed Arbitrary Loads already, but that should be purely download related right? I'm trying to view a local video file. Even so, I am viewing a blank screen with the correct time frame as the video I'm trying to view, so I'm allowed to access the file so I don't think it can be this. – user2977578 Aug 23 '16 at 22:54
  • Oh I see, How are you loading your asset? You might want to use an alternate constructor for your AVPlayer so that you can pass the Asset from file. You can use `(AVPlayerItem *)playerItemWithAsset:(AVAsset *)asset` to instantiate your asset and then use `(instancetype)initWithPlayerItem:(AVPlayerItem *)item` to instantiate your AVPlayer. – Daniel Ormeño Aug 23 '16 at 22:57
  • Got same behavior AVAsset *asset = [AVAsset assetWithURL:destination]; AVPlayerItem *item = [AVPlayerItem playerItemWithAsset:asset]; _player = [AVPlayer playerWithPlayerItem:item]; _playerVC = [AVPlayerViewController new]; _playerVC.player = _player; – user2977578 Aug 23 '16 at 22:59
  • added the nsurl print in the question – user2977578 Aug 23 '16 at 23:01
  • all playerWithURL does is create an item and creating an item creates an asset so repeated behavior is expected. – user2977578 Aug 23 '16 at 23:06
  • I'm not an objective c dude but I believe your code looks alright, why are you sending it to the main thread? is this happening on a separate thread? I'd try doing everything in the main thread to discard any issues there. – Daniel Ormeño Aug 23 '16 at 23:09
  • the UI update involved in displaying a view controller requires a main thread. I actually currently have everything regarding the video player in the main thread but it shouldn't be there since you should only include things that need to be on the main thread. I'll update my question with the source code incase you have time to play with it, I'm at a loss. It may say songs everywhere but that's because I started by playing with songs then moved to videos. – user2977578 Aug 23 '16 at 23:22

2 Answers2

0

You should setup observer for AVPlayer status to call play only when it will be ready to play. How to do it - check answers here: AVPlayer And Local Files

Community
  • 1
  • 1
Anton Malyshev
  • 8,686
  • 2
  • 27
  • 45
  • didn't work, I set the observer like this: [_player addObserver:self forKeyPath:@"status" options:0 context:nil]; and the observer method looked like this: if (object == _player && [keyPath isEqualToString:@"status"]) { if (_player.status == AVPlayerStatusReadyToPlay) { [_player play]; } else if (_player.status == AVPlayerStatusFailed) { // something went wrong. player.error should contain some information } } It was invoked, the flag AVPlayerStatusReadyToPlay was true, and the screen was still blank. – user2977578 Aug 24 '16 at 18:19
  • I'm pretty sure it has something to do with the video format or the video itself? http://a1238.phobos.apple.com/us/r1000/155/Video30/v4/12/18/48/1218480f-51fc-cf1b-1c98-06b0a33f2ee4/mzvf_5914002519860647075.640x352.h264lc.D2.p.m4v – user2977578 Aug 24 '16 at 18:20
  • Did you try another files, for example mp3 or mp4 of "easy to play" resolution like 720x400 or 640x360? – Anton Malyshev Aug 24 '16 at 18:24
0

check the following

if ((_playerVC.player.rate != 0) && (_playerVC.player.error == nil)) {
    // player is playing
} else {
   // Something wrong
}

also you can observe the rate property of the player. More info here

Community
  • 1
  • 1
hariszaman
  • 8,202
  • 2
  • 40
  • 59
  • [_player play]; if ((_playerVC.player.rate != 0) && (_playerVC.player.error == nil)) { NSLog(@"Looks like it's working!"); } else { NSLog(@"Something is wrong"); } Prints: Looks like it's working! – user2977578 Aug 24 '16 at 18:43
  • still blank and no audio, I think it has to do something with the video: http://a1238.v2.phobos.apple.com.edgesuite.net/us/r1000/155/Video30/v4/12/18/48/1218480f-51fc-cf1b-1c98-06b0a33f2ee4/mzvf_5914002519860647075.640x352.h264lc.D2.p.m4v It's blank when I click on it and view it in the browser, but when I download it via my code and open up the file I see the video on quicktime. – user2977578 Aug 24 '16 at 18:44
  • try some other video if that can be played or not – hariszaman Aug 24 '16 at 18:50
  • I tried another video from a different provider and it worked. However, if I was able to play the video when manually accessing it using quicktime after using the download function provided above, why wasn't I able to see it with the media player? – user2977578 Sep 01 '16 at 20:16
  • what is the difference between those videos . Also have a look at here http://stackoverflow.com/questions/1535836/video-file-formats-supported-in-iphone – hariszaman Sep 02 '16 at 07:27
  • different video formats. m4v is the itunes preview format and is listed in the link you gave me. I just don't understand if I can see and play it manually, why it doesn't work? – user2977578 Sep 02 '16 at 16:02