My app has 360-degree video playback and I am using GoogleVR's GVRRendererView class for it. I am trying to play a high-quality 360-degree video from the server. But the problem is that video streaming is very slow and I get below mentioned error message in the XCode console.
<AppName> [Symptoms] {
"transportType" : "HTTP Progressive Download",
"mediaType" : "HTTP Progressive Download",
"BundleID" : "AppID",
"name" : "MEDIA_PLAYBACK_STALL",
"interfaceType" : "WiredEthernet"
}
How to resolve it?
Related
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
The original video is "Sample Video 5" from https://www.appsloveworld.com/download-sample-mp4-video-mp4-test-videos/.
My /home/vagrant/Code/example/public/hls_hls.keyInfo is:
https://example.com/hls.key
/home/vagrant/Code/example/public/hls_hls.key
467216aae8a26fb699080812628031955e304a66e9e4480f9b70d31d8fe94e9a
My /home/vagrant/Code/example/public/hls_hls.key was generated using PHP: hex2bin('467216aae8a26fb699080812628031955e304a66e9e4480f9b70d31d8fe94e9a')
The ffmpeg command for encrypting the video as HLS playlist with "ts" files:
'/usr/bin/ffmpeg' '-y' '-i' 'storage/app/sample_media2/2020-02-27/Sample_Videos_5.mp4'
'-c:v' 'libx264' '-s:v' '1920x1080' '-crf' '20' '-sc_threshold' '0' '-g' '48'
'-keyint_min' '48' '-hls_list_size' '0'
'-hls_time' '10' '-hls_allow_cache' '0' '-b:v' '4889k' '-maxrate' '5866k'
'-hls_segment_type' 'mpegts' '-hls_fmp4_init_filename' 'output_init.mp4'
'-hls_segment_filename' 'storage/app/public/test/output_1080p_%04d.ts'
'-hls_key_info_file' '/home/vagrant/Code/example/public/hls_hls.keyInfo'
'-strict' '-2' '-threads' '12' 'storage/app/public/test/output_1080p.m3u8'
Then, I know from https://caniuse.com/#search=hls that Windows Chrome won't be able to play the HLS video without a library, so I use https://github.com/video-dev/hls.js/, and Windows Chrome successfully plays the encrypted video!
However, iOS Safari is unable to play it (with or without the hls.js library).
On iOS Safari, when I try to play the video, I see just a quick glimpse (less than a second) where the screen shows 0:15, so it must be reading and decrypting enough to know the correct duration of the video.
So, to debug, I log events:
const nativeHlsEvents = ['play', 'playing', 'abort', 'error', 'canplaythrough', 'waiting', 'loadeddata', 'loadstart', 'progress', 'timeupdate', 'volumechange'];
$.each(nativeHlsEvents, function (i, eventType) {
video.addEventListener(eventType, (event) => {//https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement
console.log(eventType, event);
if (eventType === 'error') {
console.error(video.error);//https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/error
}
});
});
I see in the console log:
loadstart, {"isTrusted":true}
progress, {"isTrusted":true}
play, {"isTrusted":true}
waiting, {"isTrusted":true}
error, {"isTrusted":true}
video.error, {}
I don't know how to find more details about the error.
Note that even though Windows Chrome successfully plays the video, it too shows warnings in the console log:
{"type":"mediaError","details":"fragParsingError","fatal":false,"reason":"TS packet did not start with 0x47","frag":{"...
{"type":"mediaError","details":"fragParsingError","fatal":false,"reason":"no audio/video samples found","frag":{...
Where is my problem?
I would need to buy a newer iPhone.
I see at https://en.wikipedia.org/wiki/IPhone_6#Software and https://support.apple.com/guide/iphone/supported-iphone-models-iphe3fa5df43/ios that “6s” is the oldest hardware that iOS 13 supports, and https://caniuse.com/#search=hls says HLS needs >=13.2.
Iphone devices not supported media source extension.
You should by user agent checking has iphone?
If be right, you should use iphone native video player for play hls video type or more video type
I have downloaded sample code using this link:
https://github.com/yixia/Vitamio-iOS
I tried to play RTMP video streaming, but it does no play it gives the error:
NAL 1RRE &&&& VMediaPlayer Error: (null)
I used this key:
keys[0] = #"-rtmp_live";
vals[0] = #"-1";
[mMPayer setOptionsWithKeys:keys withValues:vals];
Video does not play.
Does somebody have an idea why?
I'm trying to play a native video in a StageWebView in an Air for iPad app that plays sound and requires user interaction via the microphone.
Everything seems to work, but when I start playing the video, sound and microphone stop.
If I dispose the StageWebView, sound and mic get back but only after 15 seconds (and I need sound and mic to work at least straight after the StageWebView is released).
I tried to get this work on an iOS5 iPad1, and on an iOS6 iPad2, using Air 3.4, 3.5 and 3.6 beta. I tried to switch the mute button of the iPad, and I also tried to change the SoundMixer.audioPlaybackMode to Media and Ambient.
But it didn't worked and I'm stucked.
Here is my code that deals with the microphone :
var microphone:Microphone = Microphone.getMicrophone();
microphone.addEventListener(SampleDataEvent.SAMPLE_DATA, __micHandler);
private function micHandler(event : SampleDataEvent) : void {
trace("mic is working !");
}
For the audio :
_snd = new Sound();
_snd.load(new URLRequest(path));
_sndChannel = _snd.play();
private function soundStopHandler(event : MouseEvent) : void {
if(_sndChannel) _sndChannel.stop();
}
And for the video player :
_webview = new StageWebView();
_webview.stage = stage;
_webview.viewPort = new Rectangle(10, 120, 480, 300);
_webview.loadURL(path);
private function videoStopHandler(event : MouseEvent) : void {
if(_webview) {
_webview.dispose();
_webview = null;
}
}
Did anyone faced this problem before me ? Is there anything I forgot or did in a wrong way ?
Maybe this problem is related to the iOS System.
In iOS perspective, as far as I know, officially it is not possible. When you start the recording sessions, except for recording does not occupy it. Once you playback and recording sessions in the session must be solved. recording and playback session, the session can not be occupied simultaneously.
refer a apple documentation: Audio Session
AVAudioSessionCategoryPlayAndRecord or the equivalent kAudioSessionCategory_PlayAndRecord—Use this category for an application that inputs and outputs audio. The input and output need not occur simultaneously, but can if needed. This is the category to use for audio chat applications.
In AIR, if you code no problem. most likely this reason.
I am uploading videos to you tube from my iOS application using GData. But I want to change the access control property of the videos to "unlisted". So that, only people using my application can view the video.
I tried to use the function:
+ (GDataYouTubeAccessControl *)accessControlWithAction:(NSString *)action
permission:(NSString *)permission
in "GDataYouTubeAccessControl.h" for this, but it does not have "unlist" in the constants.
Is there any way to do this?
I did the following to upload a video as 'Unlisted'.
Since I wasn't using an updated version of the GData APIs, first I had to make the changes listed here :
[ http://code.google.com/p/gdata-objectivec-client/source/detail?r=669 ]
Then I used the following code to set the video as 'Unlisted', while uploading it to Youtube :
GDataEntryYouTubeUpload *entry;
entry = [GDataEntryYouTubeUpload uploadEntryWithMediaGroup:mediaGroup
data:data
MIMEType:mimeType
slug:filename];
[entry addAccessControl:[GDataYouTubeAccessControl
accessControlWithAction:#"list" permission:#"denied"]];
Make sure the video is NOT set as 'Private' for this to work :
[mediaGroup setIsPrivate:NO];
Got some major help from :
[ http://groups.google.com/group/gdata-objectivec-client/browse_thread/thread/da69a5ecbb6dfa42?fwc=1 ]