I have a client .ipa file that i test on my iOS device, now i have successfully got the app to run on iPhone by using Adobe Air for IOS and for this i am using Adobe Flash CC.
When i launch the app on the iPhone the video connection does not connect to the red5 streaming server and therefore can not broadcast the stream from camera to server.
I have used stagevideo. When i launch the app on a local pc with web cam and launch another app on the iOS to receive the stream on iPhone i can see the live broadcast from my pc webcam.
But i want to test the iPhone camera and send receive live streaming from red5 server.
How can i achieve this. I have placed the current code below.
import flash.display.Sprite;
import flash.display.MovieClip;
import flash.events.NetStatusEvent;
import flash.net.NetConnection;
import flash.net.NetStream;
import flash.media.Camera;
import flash.media.Microphone;
import flash.media.Video;
import flash.net.Responder;
import flash.media.StageVideo;
import flash.events.StageVideoAvailabilityEvent;
import flash.events.StageVideoEvent;
import flash.geom.Rectangle;
var nc:NetConnection;
var good:Boolean;
var netOut:NetStream;
var netIn:NetStream;
var cam:Camera;
var mic:Microphone;
var responder:Responder;
var r:Responder;
var vidOut:Video;
var vidIn:Video;
var outStream:String;
var inStream:String;
var sv:StageVideo;
stage.addEventListener(StageVideoAvailabilityEvent.STAGE_VIDEO_AVAILABILITY, onAvail);
var sva:Boolean;
function onAvail(e:StageVideoAvailabilityEvent):void{
sva = (e.availability == StageVideoAvailability.AVAILABLE);
trace(sva);
var rtmpNow:String="rtmp://192.168.1.7/test1";
nc=new NetConnection;
nc.client = this;
nc.connect(rtmpNow,"trik");
nc.addEventListener(NetStatusEvent.NET_STATUS,getStream);
}
function onRender(e:StageVideoEvent):void{
sv.viewPort = new Rectangle(0,0, 240, 180);
}
function getStream(e:NetStatusEvent):void
{
good=e.info.code == "NetConnection.Connect.Success";
if(good)
{
trace("hello");
// Here we call functions in our Java Application
setCam();
//setMic();
//Play streamed video
netIn = new NetStream(nc);
if(sva){
//Publish local video
netOut=new NetStream(nc);
//netOut.attachAudio(mic);
netOut.attachCamera(cam);
netOut.publish("tester", "live");
sv = stage.stageVideos[0];
sv.addEventListener(StageVideoEvent.RENDER_STATE, onRender);
sv.attachNetStream(netIn);
netIn.play("tester");
}else{
setVid();
vidIn.attachNetStream(netIn);
netIn.play("tester");
}
}
}
function streamNow(streamSelect:Object):void
{
trace("hello");
}
function setCam():void
{
cam=Camera.getCamera();
cam.setMode(240,180,15);
cam.setQuality(0,85);
}
function setMic():void
{
trace("hello");
mic=Microphone.getMicrophone();
trace("hello");
mic.rate =11;
trace("hello");
//mic.setSilenceLevel(12,2000);
trace("hello");
}
function setVid():void
{
trace("vid");
vidIn=new Video(240,180);
addChild(vidIn);
vidIn.x=0;
vidIn.y=0;
}
Your code mostly looks fine, but I would separate the ns.publish and ns.play parts. IMHO you shouldn't try to play until the publish is successful. Also if you're not just testing the roundtrip to the server, I would just attach the camera to the StageVideo; if that's allowed in iOS.
Related
I am using html5's video tag to show a video I select from the gallery. I'm getting an issue where the video doesn't load even though I've provided a source.
This is an Ionic/Angular project with Capacitor as the bridge, but still using Cordova plugins. Here is a prototype of my code:
my-page.page.ts
import { Camera, CameraOptions } from '#ionic-native/camera/ngx';
import { Capacitor } from '#capacitor/core';
#Component({...})
export class MyPage {
// ... some code which gets the a reference to the video element from the template
// this function is called when the user clicks a button to choose video from gallery
onPickVideo() {
const cameraOptions: CameraOptions = {
destinationType: this.camera.DestinationType.NATIVE_URI,
sourceType: this.camera.PictureSourceType.SAVEDPHOTOALBUM,
mediaType: this.camera.MediaType.VIDEO,
};
this.camera.getPicture(cameraOptions).then(videoUri => {
console.log(videoUri);
this.videoSrc = Capacitor.convertFileSrc(videoUri);
console.log(this.videoSrc);
this.videoEl.load();
this.videoEl.currentTime = 0.1;
});
}
}
my-page.page.html
<video playsinline #video>
<source [src]=".videoSrc" type="video/mp4" />
Your browser does not support the video tag.
</video>
The output of my-page.page.ts is:
file:///private/var/mobile/Containers/Data/Application/7D85727C-CE9A-4816-BC42-C97F03AFDEB4/tmp/F6DCE819-ED4A-41E4-BAFB-814500F2FB27.MOV
capacitor://localhost/_capacitor_file_/private/var/mobile/Containers/Data/Application/7D85727C-CE9A-4816-BC42-C97F03AFDEB4/tmp/F6DCE819-ED4A-41E4-BAFB-814500F2FB27.MOV
This works on desktop and on Android. It's not working on iPhone 6 with iOS 12. Untested on other iOS versions.
Some things I've tried:
Added NSCameraUsageDescription, NSPhotoLibraryUsageDescription, NSPhotoLibraryAddUsageDescription, NSMicrophoneUsageDescription
Used [src]= in the video tag, and removed the source tag. Or omitting the 'video/mp4' type
Running in live reload mode vs just building.
Chopping 'file:///' off the start of videoUri before passing it to convertFileSrc(). Or doing the former and directly setting it to videoSrc without using convertFileSrc() at all.
Solved by "sanitizing" the URL. I'm yet to learn what that really means. Here is the code in case anyone needs it
import { Camera, CameraOptions } from '#ionic-native/camera/ngx';
import { Capacitor } from '#capacitor/core';
import { DomSanitizer, SafeUrl } from '#angular/platform-browser';
#Component({...})
export class MyPage {
// ... some code which gets the a reference to the video element from the template
safeUrl: SafeUrl;
constructor(private sanitizer: DomSanitizer) {}
// this function is called when the user clicks a button to choose video from gallery
onPickVideo() {
const cameraOptions: CameraOptions = {
destinationType: this.camera.DestinationType.NATIVE_URI,
sourceType: this.camera.PictureSourceType.SAVEDPHOTOALBUM,
mediaType: this.camera.MediaType.VIDEO,
};
this.camera.getPicture(cameraOptions).then(videoUri => {
this.safeUrl = this.sanitizer.bypassSecurityTrustUrl(
Capacitor.convertFileSrc(videoUri)
);
this.videoEl.load();
this.videoEl.currentTime = 0.1;
});
}
}
Then make sure to be using safeUrl in the template [src]="safeUrl".
Has anyone else had this issue?
When I use the cordova media plugin in order to play an mp3 file on iOS, I get no error or response as to why it's not working.
I've gotten the ngCordova media plugin to work in my app on my ios emulator, using an external URL to play the audio file...however, I'm trying to build some functionality where basically you download the mp3 from an external source, save it to your device, and then play the file from there. I can't seem to get it work, even though I can verify that the file does exist. Here is my code for the function:
$scope.playAudio = function() {
document.addEventListener('deviceready', function () {
var src = cordova.file.dataDirectory + fileSrc;
var media = $cordovaMedia.newMedia(src);
var iOSPlayOptions = {
numberOfLoops: 1,
playAudioWhenScreenIsLocked : true
};
media.play(iOSPlayOptions); // iOS only!
media.play(); // Android
});
}
I should note that this functionality DOES work on my android device, but on both my ios simulator AND real device, it does absolutely nothing.
I should note that I'm using iOS 9 and xCode 7.1
Has anyone else had any issues with trying to play an audio or video file from their local device, in their app?
So it looks like I was able to solve the problem by resolving the local filepath to an internal URL using the $window.resolveLocalFileSystemURL() and src.toInternalURL() functions
$scope.playAudio = function() {
document.addEventListener('deviceready', function () {
var src = cordova.file.dataDirectory + fileSrc;
$window.resolveLocalFileSystemURL(src, function(dir){
basePath = dir.toInternalURL();
media = $cordovaMedia.newMedia(basePath);
var iOSPlayOptions = {
numberOfLoops: 1,
playAudioWhenScreenIsLocked : true
};
$scope.data.playing = true;
media.play(iOSPlayOptions); // iOS only!
//media.play(); // Android
})
});
}
I'm showing date picker using following ane
https://github.com/freshplanet/ANE-DatePicker
In iphone it always show datepicker at the bottom. I take a look at AirDatePicker.as, in iPad I can do it, but not found any way for custom positioning in iphone.
This can be done using FPNativeUI.ane:
package control
{
import flash.display.Sprite;
import flash.geom.Rectangle;
import flash.system.Capabilities;
import ru.flashpress.nui.FPNativeUI;
import ru.flashpress.nui.view.control.FPDatePicker;
import ru.flashpress.nui.events.FPDatePickerEvent;
import ru.flashpress.nui.view.system.FPWindowView;
public class DatePickerProgrammatically extends Sprite
{
private var datePicker:FPDatePicker;
public function DatePickerProgrammatically()
{
FPNativeUI.init();
//
var w:int = Capabilities.screenResolutionX;
//
var bounds:Rectangle = new Rectangle(0, 100, w, 400);
FPWindowView.window.screen.boundsFlashToNative(bounds);
//
datePicker = new FPDatePicker();
datePicker.frame = bounds;
//
datePicker.stage.addChild(datePicker);
datePicker.addEventListener(FPDatePickerEvent.VALUE_CHANGED, valueChangeHandler);
}
private function valueChangeHandler(event:FPDatePickerEvent):void
{
trace(event.date);
}
}
}
I am developing an IOS app in Flash CS6. I'm trying to load an external swf. The preloader loads the external swf. The loading itself seems to work. After loading the external swf, I add its movieclips to the stage. But strangely, on iOS devices, the movieclips are not added to stage.
Here's the code for the preloader:
package {
import flash.display.MovieClip;
import flash.display.BitmapData;
import flash.display.Loader;
import flash.display.Bitmap;
import flash.utils.getDefinitionByName;
import flash.events.Event;
import flash.events.ProgressEvent;
import flash.net.URLRequest;
import flash.system.LoaderContext;
import flash.system.ApplicationDomain;
public class Test extends MovieClip {
private var lobbyBgAssetsLoader:Loader = new Loader() ;
private var ldrContext:LoaderContext;
public function Test() {
var urlStr:String = "cards.swf";
lobbyBgAssetsLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, LobbyBgAssetsswfLoaded);
lobbyBgAssetsLoader.load(new URLRequest(urlStr));
ldrContext = new LoaderContext(false,ApplicationDomain.currentDomain,null);
}
private function LobbyBgAssetsswfLoaded(e:Event):void
{
txt.text = "loaded complete test ";
var logoSmall:Bitmap = new Bitmap();
var classDefinition:Class = lobbyBgAssetsLoader.contentLoaderInfo.applicationDomain.getDefinition("cardBg") as Class;
txt.text = "after load ";
var img:MovieClip = new classDefinition() as MovieClip;
this.addChild(img);
}
}
}
All actionscript gets converted into native Obj-C code when you compile your app for iOS. So even if your app is able to load an SWF file from the internet, the actionscript inside will not be converted to Obj-C.
Apple does not allow the actual flash player inside an iOS app, so an app cannot play back SWF content.
I am developing an IOS app using Adobe AIR, Flash and ActionScript 3 and I have divided sections up into separate SWF files. I have successfully gotten the app to load external SWFs and execute their ActionScript using the following code:
var proloader:ProLoader = new ProLoader();
proloader.load(new URLRequest("file.swf"), new LoaderContext(false, ApplicationDomain.currentDomain, null));
addChild(proloader);
Now, I would like to add a reset button that allows the user to return to the start of the first SWF from any other SWF file to restart the app. Unfortunately, it seems that whenever I try to load a SWF that has previously been loaded, nothing happens. I have read that unloading and reloading SWFs is not permitted on IOS and the fact that you are limited to one ApplicationDomain on IOS makes things difficult. However, I am still thinking there must be some workaround. I'd be okay with not ever unloading the external SWFs if that is the only way, but I still can't figure out a way to return to a SWF that was previously loaded.
Does anyone know of a way to return to a SWF that was previously loaded in IOS with Adobe Air?
You could have a static class that functions as a cache.
The cache might look something like this that I made for a menu system:
package com.rs2014.managers{
import flash.display.MovieClip;
import flash.utils.Dictionary;
import flash.events.Event;
import flash.events.EventDispatcher;
import com.events.MenuManagerEvent;
import com.menus.MenuBase;
import com.components.MenuLoader;
import com.MenuIdents;
public class MenuManager extends EventDispatcher
{
private static var instance:MenuManager
private static var allowInstantiation:Boolean = true;
public static function getInstance():MenuManager
{
if(!instance)
{
instance = new MenuManager();
allowInstantiation = false;
}
return instance
}
private const MAX_MENUS:uint = 8;
private var menuCache:Dictionary = new Dictionary()
public function MenuManager()
{
if(!allowInstantiation)
{
throw(new Error("please use the getInstance() method to obtain a handle to this singleton"));
}
}
public function getMenu(menu:String):void
{
if(menuCache[menu])
{
//This pulls from the cache if it's already been loaded before
dispatchMenu(null, menuCache[menu]);
}
else
{
//MenuLoader is a simple wrapper for Loader
var newLoader:MenuLoader = new MenuLoader();
menuCache[menu] = newLoader;
newLoader.addEventListener(Event.COMPLETE, dispatchMenu);
newLoader.source = menu;
//trace("setting up loader with source = "+menu);
}
}
private function dispatchMenu(e:Event = null, menu:MenuBase = null):void
{
if(e)
{
e.target.removeEventListener(Event.COMPLETE, dispatchMenu);
//trace(e.target.content);
//trace(e.target.content as MenuBase);
menuCache[e.target.source] = menu = e.target.content as MenuBase;
//trace(menu);
}
if(!menu)
{
throw(new Error("MenuManager Error: dispatchMenu called without menu to dispatch"));
}
this.dispatchEvent(new MenuManagerEvent(MenuManagerEvent.MENU_READY, menu))
}
}
}
I was able to solve the problem of reloading SWF's w/o ABC (no code!), I explain it all on my blog (http://www.eqsim.com/blog/?p=400) but also simply give the code on StackOverflow: Load and reload external SWF in AIR for iOS wf-in-air-for-ios/22046009#22046009
Now Adobe has a solution for separating code from the SWF, and loading the SWF externally. However, we addressed it prior to AIR 3.5 by making a class for the code only, then loading the SWF and in the code class, setting a link to the loaded SWF. When we needed to update to 4.0, the SWF reloading, even pure SWF assets, was not working in all situations, so we plugged away to find the solution I reference above.