user2977578
user2977578

Reputation: 413

Using AVPlayer and AVPlayerViewController, but audio and video not present

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.

Upvotes: 0

Views: 1294

Answers (2)

hariszaman
hariszaman

Reputation: 8424

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

Upvotes: 0

Anton Malyshev
Anton Malyshev

Reputation: 8861

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

Upvotes: 0

Related Questions