Actionscript netStream play mp4 with ios - ios

I'm trying to play a video from an app using Flash Builder 4.7, AIRSDK 31.0 and ios 12.
private function init():void{
holder.addChild(video);
this.addElement(holder);
nc.connect(null);
ns = new NetStream(nc);
ns.client = {};
ns.client.onMetaData = ns_onMetaData;
ns.client.onCuePoint = ns_onCuePoint;
video.attachNetStream(ns);
ns.play("Videos/video.mp4");
ns.addEventListener(NetStatusEvent.NET_STATUS, statusNet);
}
This works on simulators and on android devices, but not for ios devices. I've seen a couple of similiar questions but they are trying to stream an mp4 from a "http" address where mine is using a local file.
I've been asked to stick to mp4 format, although I have read using an FLV file should work.
Special considerations for H.264 video in AIR 3.0 for iOS
For H.264 video, the iOS APIs for video playback accept only a URL to a file or stream. You cannot pass in a buffer of H264 video data to be decoded.
So do I need to find a new way of playing the video other than netStream or am I best to swap to a different file type?
As a side note Adobe says to write your mp4 URLs like this:
("mp4:samples/myvideo.mp4");
My app can't find the file with "mp4:" at the front of the URL.

If you are wanting to play videos that are packaged with your iOS app it's important to ensure you are actually including them when you compile your app.
Untested but something like this should work.
var _dFile:File;
var _ns:NetStream;
var _nc:NetConnection;
var _customClient:Object;
var _video:Video;
_customClient = new Object();
_customClient.onMetaData = metaDataHandler;
_nc = new NetConnection();
_nc.connect(null);
_ns = new NetStream(_nc);
_ns.client = _customClient;
//this is the important bit for finding files within the .ipa bundle.
_dFile = File.applicationStorageDirectory.resolvePath("nameOfYourVideoDirectory/nameOfVideo.mp4");
_ns.play(_dFile.url);
_video = new Video(480, 340);
_video.attachNetStream(_ns);
_ns.addEventListener(NetStatusEvent.NET_STATUS, onNSComplete, false, 0, true);
private function metaDataHandler(infoObject:Object):void {
trace("Length of video",infoObject.duration);
}
private function onNSComplete(e:NetStatusEvent):void{
if(e.info.code == "NetStream.Buffer.Empty") {
//do something
}
}
However, I would highly recommend using an ANE to play video on mobile via the native media player. Take a look at Distriqt MediaPlayer ANE.

Related

WebApi Serving Videos on Mobile Devices

I'm using WebApi to serve videos on a website. I've tested this on all major desktop browsers and the HTML5 Video tag plays the video as expected. However, I can't get this to work on iPhones (Mobile Safari). The Get() method is never called even after pressing the play button.
WEBAPI CODE
public HttpResponseMessage Get()
{
var path = System.Web.Hosting.HostingEnvironment.MapPath("~/Content/testbw2.mp4");
var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
if (Request.Headers.Range != null)
{
try
{
HttpResponseMessage partialResponse = Request.CreateResponse(HttpStatusCode.PartialContent);
partialResponse.Content = new ByteRangeStreamContent(stream, Request.Headers.Range, _mediaType);
return partialResponse;
}
catch (InvalidByteRangeException invalidByteRangeException)
{
return Request.CreateErrorResponse(invalidByteRangeException);
}
}
else
{
HttpResponseMessage fullResponse = Request.CreateResponse(HttpStatusCode.OK);
fullResponse.Content = new StreamContent(stream);
fullResponse.Content.Headers.ContentType = _mediaType;
return fullResponse;
}
}
HTML
<video controls>
<source src="http://localhost/WebApplication24/api/range" type="video/mp4">
Your browser does not support the video tag.
</video>
If I change the video src to point directly to the file...
src="http://localhost/WebApplication24/Content/testbw2.mp4"
It works so I know this isn't an encoding issue.
Is there something I am doing wrong? I get the feeling mobile safari wont request the video src if the url doesn't end with .mp4
Here are the possible reasons (some) that your file does not work and possible solutions:
Safari is fully expecting an actually-named MP4. No other combinations of file and mime-type works. The other browsers opt for the WEBM file first, especially Chrome. source
On iOS prior to 7.0.2, Safari does support HTML5 Video, the Quicktime Player has to be installed in order for this to work. source
Also there are issues in which steaming doesn't work in iOS 7 where as local files does. source
For some reason videos would not play on iOS unless controls="true" is set. source
iOS doesn't support all the profiles that h.264 provides. You have to encode your h264 with a baseline profile only in order for it to be playable on iphone/ipad. Encoding with Miro Video Converter might help. source

Getting audio visualization using Web Audio API to work on iOS

I'm developing an HTML5 audio player for use specifically on iPhones, and am trying to get an EQ visualizer working. From what I've found there are two ways to set this up:
One where you load the mp3 file on demand using an XMLHttpRequest:
var request = new XMLHttpRequest();
request.open('GET', 'sampler.mp3', true);
request.responseType = 'arraybuffer';
request.addEventListener('load', bufferSound, false);
request.send();
function bufferSound(event) {
var request = event.target;
var buffer = myAudioContext.createBuffer(request.response, false);
source = myAudioContext.createBufferSource();
source.buffer = buffer;
}
You then use the source.noteOn and source.noteOff functions to play and pause the audio. Working this way, I AM able to get the EQ visualization going. BUT, you have to wait until the mp3 file completely loads to start playing, which won't work in our situation.
The other way to do this is to have an <audio> element already on the page, and you get the audio data from that using:
source = myAudioContext.createMediaElementSource(document.querySelector('audio'));
You then use the audio tag's play and pause functions. This solves the loading problem as it allows the media to be played immediately once the page loads... BUT, EQ visualization is gone.
Both methods show the EQ when testing on Chrome (WIN), so there seems to be something specific with iOS/iPhone that isn't allowing me to get the data from an <audio> tag, but will allow me to get it if I load the mp3 file on demand.
...
Any ideas out there?
Unfortunately Safari doesn't properly support MediaElementSource. It's a bug: Why aren't Safari or Firefox able to process audio data from MediaElementSource?

Flex/Flash Builder/Actionscript/AIR/Mobile iOS How to take video using the camera and/or browse for & view/access video stored in the 'Camera Roll"

My understanding currently is that:
CameraUI
I can use the CameraUI to access the built in camera for MediaType.VIDEO and that delegates to the built-in video camera app and lets me record a video. My app does that now.
When I stop recording and click the "Use" button, I am returned to my app and theoretically I have a valid MediaPromise.
iOS does -not- provide a valid/usable url/filename to the recorded video (or to photos) and so I would have to use a Loader to bring-in/use/access the 'recorded' video... AND... iOS does not actually create a file anywhere on the device, most importantly, in the Camera Roll where one would expect by the normal behavior when uses the system native camera/video app.
The documentation says that the Loader can load various image types and SWFs but nothing about video data, so I conclude from that that I cannot actually use the CameraUI to generate a valid MediaPromise that I can then pass to a Loader class or similar to read in the information created by the system camera and then manipulate (upload, save to applicationStorageDirectory, and/or display in one of the two video player components available in the API).
CameraRoll
I can have video entities in the iOS Camera Roll but the AS3/Air3.5 CameraRoll class won't let me view/access/reference them in any way.
Normal File I/O
All my attempts to use the Air3.5 File classes to browse to the storage location of the iOS Camera Roll have been rebuffed.
------- Questions -------
Am I correct in believing that there is a way to take video but no way to use the video that's been captured. (No way to use the resulting MediaPromise successfully).
I believe you can take video and access it using Android, but there's nothing in the documentation that says that you cannot using iOS.
Am I correct in believing that iOS sandboxes apps so that they cannot browse to video/photo storage using standard File I/O, but only through the apparently non-workable means I've tried (CameraUI & CameraRoll)
Am I wrong to think that these should be rather obvious NEEDS that one can achieve using the XCode Objective C++ etc route but the AIR Mobile Framework does not allow either because of Apple blocking functionality or because Adobe has failed to meet reasonable expectations?
One item of ironic note to convey. If I use the iOS system camera app to record a video, a thumnail of that video then appears in the Gallery/Camera Roll, and of course, I can share it or view it, or whatever... If I use AIR's CameraRoll.browseForImage(), provided I haven't used the camera to take another image, when it shows me the folder where the pictures are stored, the folder icon uses the thumbnail of the last object added... in this case, the video I took, but if I then enter the folder, the video cannot be found. It's teasing us. It knows it's there, but it is apparently forbidden fruit.
I can't answer all your questions, so this entry may not be acceptable, but I found this page while searching a solution for some the problems you described and thought that someone else may find this answer (partially) useful.
To save the movie you just took you need to open and read the data from the promise.
The iOS won't save the file anywere, so the MediaPromise.file is always null.
This is my solution to the problem:
private var camera:CameraUI;
private var dataInput:IDataInput;
public function recordVideo():void
{
// Start the camera and ask for a video
camera = new CameraUI();
camera.addEventListener(MediaEvent.COMPLETE, onCameraComplete);
camera.launch(MediaType.VIDEO);
}
private function onCameraComplete(event:MediaEvent):void
{
// event.data is a MediaPromise and MediaPromise.open() returns a IDataInput
// Let's cast it to a dispatcher and check when it's complete
dataInput = event.data.open();
var dispatcher:IEventDispatcher = IEventDispatcher(dataInput);
dispatcher.addEventListener(Event.COMPLETE, onDataInputComplete);
}
private function onDataInputComplete(event:Event):void
{
// We can do whatever we want with the data, so we'll store it in a File
var file:File = new File();
var bytes:ByteArray = new ByteArray();
var stream:FileStream = new FileStream();
// Reading the data from the opened MediaPromise
dataInput.readBytes(bytes);
stream.open(file, FileMode.WRITE);
stream.writeBytes(bytes, 0, bytes.bytesAvailable);
stream.close();
}
Also, I'm still looking for a way to put the movie in the CameraRoll

How to stop video autoplaying (stageWebView in Air for iOS - Flash)

Is there a reason a stageWebView may be autoplaying? As soon as it loads, it will start playing, but the funny thing with it is that the Play Icon stays there even while it's already playing. I was hoping to have it paused when it loads and only play if the user requires it to be played.
import flash.geom.Rectangle;
import flash.media.StageWebView;
import flash.filesystem.File;
var webView:StageWebView = new StageWebView();
var path:String = new File(new File("app:/video.mp4").nativePath).url;
webView = new StageWebView();
webView.stage = this.stage;
webView.viewPort = new Rectangle(100, 100, 400, 300);
webView.loadURL(path);
I can't pick anything out of my code that looks like it would be causing the error?
Consider using StageVideo instead.
It is supported on iOS.
From Adobe Air 21 release notes (http://fpdownload.macromedia.com/pub/labs/flashruntimes/shared/air21_flashplayer21_releasenotes.pdf)
Media Auto Play for iOS & Android Starting AIR 21, we are introducing Media Auto Play support for AIR iOS & Android applications. Using this feature, ActionScript developers can enable media auto play inside StageWebView. To enable this, autoplay should also be enabled in the HTML5 video tag. (More info on HTML5 video tag : http://www.w3schools.com/tags/tag_video.asp). Please use swf-version 32 or greater and namespace 21.0 or greater to access this feature.
var webView:StageWebView = new StageWebView();
webView.stage = stage;
webView.viewPort = new Rectangle( 0, 0, 400, 300 );
webView.mediaPlaybackRequiresUserAction = false;// To enable autoplay in given web view
webView.addEventListener(Event.COMPLETE, <handleComplete>);
webView.addEventListener(ErrorEvent.ERROR, <handleError>);
webView.loadURL("http://any/webpage/with/autoplay/enabled/video.html”)

Save encoded .mp3 to applicationStorageDirectory Adobe Air iOS

I'm developing an iOS iPad app w/ Flash CS5.5 AIR v.3.1
I'm using ShineMp3Encoder to encode a Wav to a Mp3 from:
https://github.com/kikko/Shine-MP3-Encoder-on-AS3-Alchemy
Basically it converts a byteArray (wav) to a byteArray (mp3) or "mp3encoder.mp3Data" in the code.
I have no trouble saving this using a (new FileReference()).save(mp3Data, filename); but because this is being used in a iOS AIR app I wanted to switch to using the File.applicationStorageDirectory so that I could put the saved mp3 into it's own folder to keep organized. When I run the code it goes through all the steps, converts the wav to mp3, and then says that it saves but doesn't with no errors. The sound IS stored in memory, as it is able to be played back until the app is closed. I've changed the resolvePath to the root folder, myApp/, and to /sounds - None of which work. I've never attempted to do this before so I'm a little lost why no file is being created. Anyone with any suggestions would help a lot.
function onEncoded(e:Event):void{
myTI.text = "Mp3 encoded and saved. Press Play.";
mp3encoder.mp3Data.position = 0;
var myDate:Date = new Date();
var theDate:String = myDate.monthUTC.toString() + myDate.dayUTC.toString()
+ myDate.hoursUTC.toString() + myDate.minutesUTC.toString()
+ myDate.secondsUTC.toString();
var file:File = File.applicationStorageDirectory.resolvePath("myApp/sounds/myVoice+"+theDate+".mp3");
var fileStream:FileStream = new FileStream;
fileStream.open(file,FileMode.UPDATE);
fileStream.writeBytes(mp3encoder.mp3Data);
fileStream.close();
}
Untested but try this. If it works, modify the filename to be dynamic as you require.
var myfilename:File = File.applicationStorageDirectory;
myfilename = myfilename.resolvePath("myVoice.mp3");
var outputStream:FileStream = new FileStream();
outputStream.open(myfilename,FileMode.WRITE);
outputStream.writeBytes(mp3encoder.mp3Data,0,mp3encoder.mp3Data.length);
outputStream.close();
I know my answer is little bit late, but maybe it will be useful for somebody who will find this post in future.
When you develop on Windows in Adobe AIR and try to save something in File.applicationStorageDirectory it will NOT saved in the same folder like your swf or fla file.
It will be saved here:
C:\Users[WIN_LOGIN]\AppData\Roaming[APP_ID]\Local Store
Your APP_ID you will find and set in Publish Settings for IOS.

Resources