Red5 Server, Flash Client, Voice Chat/Conference Voice Chat Yahoo Style - actionscript-3

I don't know if anyone remembers the old Yahoo chat rooms, but I currently have an existing chat on my website. It is Ajax Chat by blueimp. All is well and it works just fine. I am wanting to add a "talk" button so that a user can press it and talk and everyone else in the chat room can hear. What I have works sort of. But after a few minutes of use not all users can hear the person talking. So my question is, how can I fix this so that users can all continue to hear whoever is talking?
Here is the code:
import flash.net.NetConnection;
import flash.net.NetStream;
import flash.events.*;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.net.URLVariables;
import flash.net.URLLoaderDataFormat;
import flash.net.URLRequestMethod;
import flash.media.Microphone;
import flash.media.Sound;
var Mic:Microphone;
var aud:Sound;
var nc:NetConnection = new NetConnection;
nc.client = this;
var istream:NetStream;
var ostream:NetStream;
Security.showSettings("2");
if(Microphone.names.length <= 0) {
//they has no mic
} else {
Mic = Microphone.getMicrophone();
Mic.setUseEchoSuppression(true);
Mic.setLoopBack(false);
Mic.addEventListener(ActivityEvent.ACTIVITY, activityHandler);
Mic.addEventListener(StatusEvent.STATUS, statusHandler);
}
btnTalk.addEventListener(MouseEvent.MOUSE_DOWN, talkDown);
btnTalk.addEventListener(MouseEvent.MOUSE_UP, talkUp);
nc.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
nc.connect("rtmp://MYSERVER:1935/oflaDemo");
function talkDown(e:MouseEvent):void {
trace("talking");
ostream.publish("charchar");
istream.receiveAudio(false);
}
function talkUp(e:MouseEvent):void {
trace("done talking");
ostream.close();
istream.receiveAudio(true);
}
function netStatusHandler(event:NetStatusEvent):void {
trace(event.info.code)
ostream = new NetStream(nc);
istream = new NetStream(nc);
istream.play("charchar");
ostream.attachAudio(Mic);
}
function activityHandler(event:ActivityEvent):void {
trace("activityHandler: " + event);
}
function statusHandler(event:StatusEvent):void {
trace("statusHandler: " + event);
}
Example: 3 users load the page and can all hear. After a few times of someone talking, User1 can hear User2, but User3 cannot hear User1. It is mixed and matched who can hear who, but this is an example of what's happening.

If you're going to use the same stream "charchar" for all clients, you will need to implement some sort of lock to prevent a race condition. That will be incredibly tricky btw and will most certainly require server side modification of the code.

Related

SWF cannot load local XML file in browser

I need a local SWF to load a local XML file when running in a browser. The SWF and XML are placed locally on my HD in the same directory, which - as far as I understand - should be OK? But in a browser the XML does not load - output reads "begin" and I cannot get any of the events to trigger. Whereas when running directly from Animate or in the Flash player it works and the output reads "success".
package {
import flash.display.MovieClip;
import flash.errors.IOError;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.text.TextField;
import flash.events.SecurityErrorEvent;
import flash.events.HTTPStatusEvent;
public class main extends MovieClip {
private var output:TextField;
public function main() {
output = new TextField();
output.width = 600;
output.text = "begin";
addChild(output);
var urlLoader:URLLoader = new URLLoader();
urlLoader.addEventListener(Event.COMPLETE, function(e:Event){
output.text = "success";
});
urlLoader.addEventListener(HTTPStatusEvent.HTTP_STATUS, function(e:Event) {
output.text = "http status event";
});
urlLoader.addEventListener(IOErrorEvent.IO_ERROR, function(e:Event) {
output.text = "io error";
});
urlLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function(e:SecurityErrorEvent) {
output.text = "security error";
});
urlLoader.load(new URLRequest("test.xml"));
}
}
}
As suggested in the comments, I have tried to set the "Global Security Settings Panel" to "Always allow" but it does not make a difference.
Local-with-filesystem setup is tricky, the easiest way is to go to Flash Player Global Security Settings and add the folder you are debugging in to the list of always trusted locations. Checking the "Always Allow" option might not work, no idea why, as I said - tricky.

fileReference.save; works in swf but doesn't work when the swf embeded in the html

This code works properly when published by Flash CS 5.5 as .swf (it prompts to browse where to save the file). However, when it is published to HTML, it doesn't work (doesn't prompt to browse the destination). Is it security issue or other problem?
import flash.display.Sprite;
import flash.media.Microphone;
import flash.system.SecurityDomain;
import org.bytearray.micrecorder.*;
import org.bytearray.micrecorder.events.RecordingEvent;
import org.bytearray.micrecorder.encoder.WaveEncoder;
import flash.events.Event;
import flash.net.FileReference;
import flash.utils.setTimeout;
var mic:Microphone;
var waveEncoder:WaveEncoder = new WaveEncoder();
var recorder:MicRecorder = new MicRecorder(waveEncoder);
var fileReference:FileReference = new FileReference();
mic = Microphone.getMicrophone();
mic.setSilenceLevel(0);
mic.gain = 100;
mic.setLoopBack(true);
mic.setUseEchoSuppression(true);
Security.showSettings("2");
addListeners();
function addListeners():void
{
setTimeout(startIntroTime,3000);
function startIntroTime():void
{
startRecording();
setTimeout(stopRecording,5000);
}
recorder.addEventListener(Event.COMPLETE, recordComplete);
}
function startRecording():void
{
if (mic != null)
{
recorder.record();
}
}
function stopRecording():void
{
recorder.stop();
mic.setLoopBack(false);
}
function recordComplete(e:Event):void
{
fileReference.save(recorder.output, "recording.wav");
}
Have a look at the documentation: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/FileReference.html#save()
It says :
In Flash Player, you can only call this method successfully in response to a user event (for example, in an event handler for a mouse click or keypress event). Otherwise, calling this method results in Flash Player throwing an Error exception. This limitation does not apply to AIR content in the application sandbox.
So it is not possible and probably a security thing.

Playing successive wav sounds in as3

I am trying to play through AS3 external wav sounds in a successive way. The obvious way to do it is to use this algorithm:
1. play sound 1
2. when sound 1 is done, play sound 2
etc.
The problem is that I fail the step number 2 (the "when sound 1 is done" part).
Please answer for wav sounds only, NOT mp3.
Here is my code:
package
{
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.events.Event;
import flash.utils.ByteArray;
import flash.media.Sound;
import org.as3wavsound.WavSound;
import org.as3wavsound.WavSoundChannel;
public final class Main extends Sprite
{
public final function Main():void
{
playB.addEventListener(MouseEvent.MOUSE_UP, loadWav);
}
private final function loadWav(e:MouseEvent):void
{
var urlRequest:URLRequest = new URLRequest('Phone.wav');
var wav:URLLoader = new URLLoader();
wav.dataFormat = 'binary';
wav.load(urlRequest);
wav.addEventListener(Event.COMPLETE, playWav);
}
private final function playWav(e:Event):void
{
var tts:WavSound = new WavSound(e.target.data as ByteArray);
tts.play();
}
}
}
(This is step 1 of course)
Thanx
Try putting your sound into a SoundChannel - which is returned from the play command, then listen for the complete event:
private final function playWav(e:Event):void
{
var tts:WavSound = new WavSound(e.target.data as ByteArray);
var channel:WavSoundChannel = tts.play();
channel.addEventListener(Event.SOUND_COMPLETE, completeHandler)
}
private function completeHandler(e:Event):void {
//play next sound
}

as3 Adobe Air access iPad device camera

Is there a way you can use as3 to access iPad's camera?
I mean start the Camera within the app itself
have ability take a shoot and save the image to byteArray and applying the image to the background or doing some manipulation
I have done some research most of them just showing how to access the android devices.
Thanks for any suggestion or help.
Yes, you can absolutely do this. The beauty of Flash is that the code to do it is the same that you would use on Android or a PC.
Literally, you can do this to connect the camera to a Video object:
var camera:Camera = Camera.getCamera();
var video=new Video();
video.attachCamera(camera);
this.addChild(video); // 'this' would be a Sprite or UIComponent, etc...
There's a lot more to do if you want to do something useful, but it's fairly straight forward once you get started :)
bluebill1049, I'm not certain from the thread if you got what you were looking for, but I did see your request for the whole class. I found the same information (that Jason Sturges posted in his answer) in this post.
take photo using Adobe Builder (flex) for iOS
Unlike his reply here, his reply to that post had had a link to a great tutorial on building a mobile app and it was from that tutorial that this code was lifted/quoted. It requires an event class (event.CameraEvent - only a few lines) that's contained in that project/tutorial so it's important to be able to go back to the source, as it were. That source is located here:
http://devgirl.org/files/RIAUnleashed/
My thanks to Jason. Just so you don't have to dig, here's the event class that's missing from the quote:
package events
{
import flash.events.Event;
import flash.filesystem.File;
public class CameraEvent extends Event
{
public static const FILE_READY:String = "fileReady";
public var file:File;
public function CameraEvent(type:String, file:File=null, bubbles:Boolean = true, cancelable:Boolean = true)
{
super(type, bubbles, cancelable);
this.file = file;
}
}
}
Hope that helps!
Using the loader is not the only way to access the image bytes on iOS. It turns out the data is already in JPEG format to begin with, so encoding it again is not necessary.
Just do a mediaPromise.open() to get at the bytes and save them directly instead.
XpenseIt example code offers this camera implementation:
Class: CameraUtil:
package utils
{
import events.CameraEvent;
import flash.display.BitmapData;
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.MediaEvent;
import flash.filesystem.File;
import flash.filesystem.FileMode;
import flash.filesystem.FileStream;
import flash.media.CameraRoll;
import flash.media.CameraUI;
import flash.media.MediaPromise;
import flash.media.MediaType;
import flash.utils.ByteArray;
import mx.events.DynamicEvent;
import mx.graphics.codec.JPEGEncoder;
[Event(name = "fileReady", type = "events.CameraEvent")]
public class CameraUtil extends EventDispatcher
{
protected var camera:CameraUI;
protected var loader:Loader;
public var file:File;
public function CameraUtil()
{
if (CameraUI.isSupported)
{
camera = new CameraUI();
camera.addEventListener(MediaEvent.COMPLETE, mediaEventComplete);
}
}
public function takePicture():void
{
if (camera)
camera.launch(MediaType.IMAGE);
}
protected function mediaEventComplete(event:MediaEvent):void
{
var mediaPromise:MediaPromise = event.data;
if (mediaPromise.file == null)
{
// For iOS we need to load with a Loader first
loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loaderCompleted);
loader.loadFilePromise(mediaPromise);
return;
}
else
{
// Android we can just dispatch the event that it's complete
file = new File(mediaPromise.file.url);
dispatchEvent(new CameraEvent(CameraEvent.FILE_READY, file));
}
}
protected function loaderCompleted(event:Event):void
{
var loaderInfo:LoaderInfo = event.target as LoaderInfo;
if (CameraRoll.supportsAddBitmapData)
{
var bitmapData:BitmapData = new BitmapData(loaderInfo.width, loaderInfo.height);
bitmapData.draw(loaderInfo.loader);
file = File.applicationStorageDirectory.resolvePath("receipt" + new Date().time + ".jpg");
var stream:FileStream = new FileStream()
stream.open(file, FileMode.WRITE);
var j:JPEGEncoder = new JPEGEncoder();
var bytes:ByteArray = j.encode(bitmapData);
stream.writeBytes(bytes, 0, bytes.bytesAvailable);
stream.close();
trace(file.url);
dispatchEvent(new CameraEvent(CameraEvent.FILE_READY, file));
}
}
}
}

Flash Webcam Permissions

I'm having an issue with flash, which I am not really familiar with. I'm basing this code off of what came with the wowza media server in the video chat example, but unlike that example flash is not prompting me for whether or not to allow the video camera.
Below is my actionscript:
import flash.events.MouseEvent;
import flash.events.NetStatusEvent;
import flash.media.Camera;
import flash.media.Microphone;
import flash.media.Video;
import flash.net.NetConnection;
import flash.net.NetStream;
import flash.system.Security;
import flash.system.SecurityPanel;
import flash.display.Sprite;
import flash.text.TextField;
import flash.events.StatusEvent;
public class QandA extends Sprite {
Security.LOCAL_TRUSTED;
private var nc:NetConnection = null;
private var camera:Camera;
private var microphone:Microphone;
private var nsPublish:NetStream = null;
private var nsPlay:NetStream = null;
private var videoCamera:Video;
public var prompt:TextField;
public function QandA():void {
stage.align = "TL";
stage.scaleMode = "noScale";
videoCamera = new Video(160,120);
addChild(videoCamera);
camera = Camera.getCamera();
microphone = Microphone.getMicrophone();
if (camera.muted) {
trace("Camera Muted");
Security.showSettings(SecurityPanel.CAMERA);
camera.addEventListener(StatusEvent.STATUS, statusHandler);
} else {
startCamera();
}
}
private function statusHandler(e:StatusEvent):void {
if (e.code == "Camera.Unmuted") {
trace("Camera Unmuted");
startCamera();
camera.removeEventListener(StatusEvent.STATUS, statusHandler);
} else {
trace("StatusEvent: " + e.code + " " + e.toString());
}
}
private function startCamera():void {
// here are all the quality and performance settings that we suggest
camera.setMode(160, 120, 12, false);
camera.setQuality(0, 75);
camera.setKeyFrameInterval(24);
microphone.rate = 11;
microphone.setSilenceLevel(0);
nc = new NetConnection();
nc.connect("rtmp://localhost/live/");
// get status information from the NetConnection object
nc.addEventListener(NetStatusEvent.NET_STATUS, ncOnStatus);
}
private function nsPublishOnStatus(infoObject:NetStatusEvent):void
{
trace("nsPublish: "+infoObject.info.code+" ("+infoObject.info.description+")");
}
private function ncOnStatus(infoObject:NetStatusEvent):void
{
trace("nc: "+infoObject.info.code+" ("+infoObject.info.description+")");
nsPublish = new NetStream(nc);
nsPublish.addEventListener(NetStatusEvent.NET_STATUS, nsPublishOnStatus);
nsPublish.bufferTime = 0;
nsPublish.publish("testing");
// attach the camera and microphone to the server
nsPublish.attachCamera(camera);
nsPublish.attachAudio(microphone);
}
}
I'm fairly confident it's something simple; as I've seen this code in/on countless sites when discussing how to publish to a live server.
Any help would be greatly appreciated, I've attempted using this code on a webserver to see if it was simply local security settings, but that was not the case.
Logs I receive when debugging the application in Flash CS5:
Attempting to launch and connect to Player using URL D:\development\qanda\qandaHost.swf
[SWF] D:\development\qanda\qandaHost.swf - 3583 bytes after decompression
Camera Muted
nc: NetConnection.Connect.Success (Connection succeeded.)
nsPublish: NetStream.Publish.Start (Publishing testing.)
Below is wrong:
Security.showSettings(SecurityPanel.**CAMERA**);
You should write:
Security.showSettings(SecurityPanel.**PRIVACY**);
I wasn't attaching the camera to the video, thus I couldn't see myself -- even though the video was in fact streaming.
private function startCamera():void {
trace("Attempting to start camera");
// here are all the quality and performance settings that we suggest
camera.setMode(160, 120, 12, false);
camera.setQuality(0, 75);
camera.setKeyFrameInterval(24);
videoCamera.attachCamera(camera);
microphone.rate = 11;
microphone.setSilenceLevel(0);
}