AVURLAsset tracks is empty, but video/audio is playable - ios

I have video that lives here:
http://195.16.112.71/adaptive/66aebabb-2632-44fc-abf1-df29bca6b941.video/66aebabb-2632-44fc-abf1-df29bca6b941.m3u8
Ffmpeg says that this video has 5 tracks and it's correctly.
But if I use AVURLAsset with that link it says me that there isn't any tracks:
NSArray* const tracks = asset.tracks; // it's empty
I modified Apple's StichedStreamPlayer sample to reproduce this problem, it lies here:
https://yadi.sk/d/hV3jfbx1Z9sfC
Simply click 'Load Movie', than the 'Play' button - movie plays perfectly, but if you check tracks variable in prepareToPlayAsset function you find it's empty.
The question is: why it's empty if in reality the video has 5 tracks and how this video could be playing if no tracks exist, as AVURLAsset says?
Thanks for your help in advance!

If you are directly streaming the video then it won't have tracks. You can download the file and ask for the tracks of the video file asset.

Related

Why can't I play certain .m3u8 items with AVPlayer?

I'm working on a project where I have an instance of AVPlayer capable of playing different audio content that I retrieve from a backend, from podcast to music and streamings. Every content has two types of urls: one with mp3 and another with a m3u8 file. All the mp3 files work good. However some m3u8 files work fine and others don't. In particular, those who don't work cause the AVPlayer to crash with the error:
Error Domain=AVFoundationErrorDomain Code=-11819 "Cannot Complete Action"
UserInfo={NSLocalizedRecoverySuggestion=Try again later.,
NSLocalizedDescription=Cannot Complete Action.}
I don't understand what the problem is. According to this answer it is a wrong Manifest file, which in my case is - for example - the following:
#EXTM3U
#EXT-X-MEDIA:TYPE=AUDIO,URI="_64/index.m3u8",GROUP-ID="2#48000-64000",NAME="AAC 64",DEFAULT=NO,AUTOSELECT=NO
#EXT-X-MEDIA:TYPE=AUDIO,URI="_80/index.m3u8",GROUP-ID="2#48000-80000",NAME="AAC 80",DEFAULT=NO,AUTOSELECT=NO
#EXT-X-MEDIA:TYPE=AUDIO,URI="_96/index.m3u8",GROUP-ID="2#48000-96000",NAME="AAC 96",DEFAULT=NO,AUTOSELECT=NO
#EXT-X-STREAM-INF:BANDWIDTH=133336,CODECS="mp4a.40.2",AUDIO="2#48000-96000"
_96/index.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=100641,CODECS="mp4a.40.2",AUDIO="2#48000-64000"
_64/index.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=116989,CODECS="mp4a.40.2",AUDIO="2#48000-80000"
_80/index.m3u8
On the Apple forum, I found this answer which says iOS 14+ is on fault. Unfortunately I cannot test with an iOS 13 physical device.
Do you have any suggestion?
Tested on Xcode 13.1 with iPhone 7plus with iOS 15.0.2.
Finally I found a solution for this issue. What worked for me was this. I believe the problem was that my manifest files were structured like the following:
#EXT-X-MEDIA:TYPE=AUDIO,URI="_64/index.m3u8", GROUP-ID="1#48000-64000",NAME="Audio 64",DEFAULT=NO,AUTOSELECT=NO
In particular they had DEFAULT=NO,AUTOSELECT=NO. Therefore before calling replaceCurrentItem I now do the following:
let asset = AVAsset(url: url)
let playerItem = AVPlayerItem(asset: asset)
for characteristic in asset.availableMediaCharacteristicsWithMediaSelectionOptions {
if let group = asset.mediaSelectionGroup(forMediaCharacteristic: AVMediaCharacteristic.audible) {
if let option = group.options.first {
playerItem.select(option, in: group)
}
}
}
This makes all my HLS audio playable by the AVPlayer.
I dont see version in your .m3u8. Try adding #EXT-X-VERSION:03 into your playlist. AVPlayer does need to have version included in playlist (Android EXO player does not need it). Here is example of playlist that might work:
#EXTM3U
#EXT-X-VERSION:03
#EXT-X-MEDIA:TYPE=AUDIO,URI="_64/index.m3u8",GROUP-ID="2#48000-64000",NAME="AAC 64",DEFAULT=NO,AUTOSELECT=NO
#EXT-X-MEDIA:TYPE=AUDIO,URI="_80/index.m3u8",GROUP-ID="2#48000-80000",NAME="AAC 80",DEFAULT=NO,AUTOSELECT=NO
#EXT-X-MEDIA:TYPE=AUDIO,URI="_96/index.m3u8",GROUP-ID="2#48000-96000",NAME="AAC 96",DEFAULT=NO,AUTOSELECT=NO
#EXT-X-STREAM-INF:BANDWIDTH=133336,CODECS="mp4a.40.2",AUDIO="2#48000-96000"
_96/index.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=100641,CODECS="mp4a.40.2",AUDIO="2#48000-64000"
_64/index.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=116989,CODECS="mp4a.40.2",AUDIO="2#48000-80000"
_80/index.m3u8

saving VLC player snapshot with filename same as video filename

How can I save a snapshot from VLC player with a filename exactly the same as the video file playing. i.e. playing video file examplevideo52.mp4 I want to be able to save a snapshot with the filename examplevideo52.jpg
With the existing settings, the closest you can get for a video file named sample.mp4 is a snapshot with name sample.mp4-0001.jpg.
You can achieve this using following settings. Settings -> Video -> Video Snapshots
You can find more tags at - https://wiki.videolan.org/Documentation:Play_HowTo/Format_String/

Playing audio files continually using audio recorded url

I am newcomer in Objective-C and have experience only 12 months in iPhone development.
I am recording audio files in One UIViewController, and playing on another UIViewController. For playing purpose i am saving the date string for generation of url,it is fine working properly,
But ,now my problem is i want to play previous audio record file for some time after that i want to play next audio file using url . i am saving all the data using nsuser dafaults please help me
NSM![enter image description here][1]utableArray *dateString;
NSURL recordFile = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingString:[self.dateString objectAtIndex:sender.tag]]];
For playing
player = [[AVAudioPlayer alloc] initWithContentsOfURL:recordFile error:&error];
from fig when i click a tag 2 i want to play first 5 sec tag1 after that i want to play tag2
Record the audio -> Save the audio in the Temp -> Track the saved path of the audio file (You can store this saved path in an array) . Repeat the same steps for the next file.
Use AVQueuePlayerfor playing items one after the other.

AVFoundation: Video to OpenGL texture working - How to play and sync audio?

I've managed to load a video-track of a movie frame by frame into an OpenGL texture with AVFoundation. I followed the steps described in the answer here: iOS4: how do I use video file as an OpenGL texture?
and took some code from the GLVideoFrame sample from WWDC2010 which can be downloaded here.
How do I play the audio-track of the movie synchronously to the video? I think it would not be a good idea to play it in a separate player, but to use the audio-track of the same AVAsset.
AVAssetTrack* audioTrack = [[asset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
I retrieve a videoframe and it's timestamp in the CADisplayLink-callback via
CMSampleBufferRef sampleBuffer = [self.readerOutput copyNextSampleBuffer];
CMTime timestamp = CMSampleBufferGetPresentationTimeStamp( sampleBuffer );
where readerOutput is of type AVAssetReaderTrackOutput*
How to get the corresponding audio-samples?
And how to play them?
Edit:
I've looked around a bit and I think, best would be to use AudioQueue from the AudioToolbox.framework using the approach described here: AVAssetReader and Audio Queue streaming problem
There is also an audio-player in the AVFoundation: AVAudioPlayer. But I don't know exactly how I should pass data to its initWithData-initializer which expects NSData. Furthermore, I don't think it's the best choice for my case because a new AVAudioPlayer-instance would have to be created for every new chunk of audio samples, as I understand it.
Any other suggestions?
What's the best way to play the raw audio samples which I get from the AVAssetReaderTrackOutput?
You want do do an AV composition. You can merge multiple media sources, synchronized temporally, into one output.
http://developer.apple.com/library/ios/#DOCUMENTATION/AVFoundation/Reference/AVComposition_Class/Reference/Reference.html

Not able to play the .wav sound which i recorded through coding in blackberry

i have tried to record the audio in wav format and i succeeded but when i try to play that file, it gives an error that 'media file is of unsupported format'.
the main portion of code is as follows:
player = Manager.createPlayer("capture://audio?encoding=pcm&rate=44100&bits=16&channels=1");
player.realize();
controller = (RecordControl) player.getControl("RecordControl");
controller.setRecordLocation("file:///SDCard/BlackBerry/voicenotes/voice.wav");
//controller.setRecordSizeLimit(396900);
controller.startRecord();
player.start();
Thread.sleep(7000);
controller.commit();
player.close();
This code works well and it gave me a voice.wav file but i am not able to play this file.Is there is something which i forget?
Thanks in advance.
Sounds like the same problem as here:
http://supportforums.blackberry.com/t5/Java-Development/Bug-in-media-Manager-Player/td-p/1009027/page/2
Essentially, you need to add the RIFF/WAVE-header for the recorded data yourself, see the last post on the thread for example.

Resources