Javascript 能否在Flash实例之间传递摄影机和麦克风对象?

Javascript 能否在Flash实例之间传递摄影机和麦克风对象?,javascript,flash,webcam,microphone,Javascript,Flash,Webcam,Microphone,我正在开发一个HTML5应用程序,它需要与Flash接口,以访问本地媒体(例如,网络摄像头和麦克风),并在远程浏览器之间传输音频视频。但在这个应用程序中,我需要本地网络摄像头显示在屏幕的一部分,由不同的HTML元素与远程网络摄像头显示分开。我很确定这意味着我需要运行我的Flash应用程序的多个实例。但我认为一次只能抓取一个网络摄像头实例,这意味着我需要能够在Flash实例之间共享这些网络摄像头和麦克风对象:一个显示本地网络摄像头,另一个与远程网络摄像头通信并显示远程网络摄像头。有可能吗?例如,我

我正在开发一个HTML5应用程序,它需要与Flash接口,以访问本地媒体(例如,网络摄像头和麦克风),并在远程浏览器之间传输音频视频。但在这个应用程序中,我需要本地网络摄像头显示在屏幕的一部分,由不同的HTML元素与远程网络摄像头显示分开。我很确定这意味着我需要运行我的Flash应用程序的多个实例。但我认为一次只能抓取一个网络摄像头实例,这意味着我需要能够在Flash实例之间共享这些网络摄像头和麦克风对象:一个显示本地网络摄像头,另一个与远程网络摄像头通信并显示远程网络摄像头。有可能吗?例如,我可以通过ExternalInterface将照相机和麦克风实例传递给JavaScript,然后将它们传递回Flash对象的单独实例吗

换句话说,我正在考虑一个ActionScript类,它看起来像这样(当然要简化得多):

我用JavaScript检索它们,如下所示:

var localUser = $('#localUser')[0];
localUser.getUserMedia();
var mic = localUser.getMicrophone();
var cam = localUser.getCamera();
var remoteUser = $('#remoteUser')[0];
remoteUser.setMicrophone(mic);
remoteUser.setCamera(cam);
然后将它们传递回实际与远程用户通信的实例,如下所示:

var localUser = $('#localUser')[0];
localUser.getUserMedia();
var mic = localUser.getMicrophone();
var cam = localUser.getCamera();
var remoteUser = $('#remoteUser')[0];
remoteUser.setMicrophone(mic);
remoteUser.setCamera(cam);

这样做有什么已知的陷阱吗?有没有更好的方法来处理这个问题?(在你提问之前,是的,在没有其他建议的情况下,我计划将其编码,我会让所有人知道我发现了什么-只是想在我开始之前知道是否有任何已知的陷阱或替代方案。:-)

您不能通过
外部接口
摄像头
麦克风
等对象传递给Javascript。当您使用
ExternalInterface
与Javascript通信时,您传递的任何数据都会封送为XML格式。因此,此时,相机/麦克风不再是闪光灯
相机
麦克风
对象

您可能会发现,在某些浏览器/操作系统中,尝试同时从两个单独的SWF访问同一个摄像头是可行的。然而,在其他情况下,它失败了。我在访问摄像头的两个完全无关的网站上看到过这种行为


SWF可以使用该类进行相互通信,尽管我从未用相机或麦克风尝试过类似的方法。

值得一提的是,这是我最终采用的方法(或多或少),而且它是有效的。复杂,有点脆弱,但它可以工作:

// A typical 1:1 communication will involve four instances of the FlashMediaObject class:
// Instance1 (Initiator Sender): Displays local video, streams local video out to Instance4
// Instance2 (Initiator Receiver): Receives and displays video from Instance3
// Instance3 (Responder Sender): Displays local video, streams local video out to Instance2
// Instance4 (Responder Receiver): Receives and displays video from Instance1

// The workflow needs to go something like this:
// (1) Both: Room.onSessionAdded():     
//          SignalR makes both the JS clients for both the Initiator and the Responder aware of each other (i.e., their SessionId's).
// (2) Initiator: writeLocalMediaElement() -> fmo1.Connect():
//          Instance1 connects to Adobe's rtmfp service, gets its nearId, and passes it up to JS.
// (3) Responder: writeLocalMediaElement() -> fmo3.connect():
//          Instance3 connects to Adobe's rtmfp service, gets its peerId, and passes it up to JS.
// (4) Responder: prepareForCall() -> fmo4.connect():           
//          Instance4 connects to Adobe's rtmfp service, gets its peerId, and passes it up to JS.
// (5) Initiator: call() -> prepareForCall() -> fmo2.Connect():
//          Instance2 connects to Adbobe's rtmfp service, gets its nearId, and passes it up to JS.
// (6) Initiator: call() -> server.flashOffer():
//          The Initiator's JS controller contacts the Responder's JS (via SignalR), and passes it the two rtmfp ID's.
// (7) Responder: handleFlashOffer() -> fmo3.call():            
//          The Responder's JS controller passes the peerId for Instance2 (Initiator Receiver) to Instance3 (Responder Sender).
//          Instance3 begins publishing its video to Instance 2.
// (8) Responder: handleFlashOffer() -> fmo4.prepareForCall():
//          The Responder's JS controller passes the peerId for Instance1 (Initiator Sender) to Instance4 (Responder Receiver)
//          Instance4 prepares to receive a call from Instance1.
// (10) Responder: handleFlashOffer() -> server.flashAnswer():  
//          The Responder's JS controller contacts the Initiator's JS (via SignalR), and passes it the two peer ID's.
// (11) Initiator: handleFlashAnswer() -> fmo1.call():
//          The Initiator's JS controller passes the peerId for Instance4 (Responder Receiver) to Instance1 (Initiator Sender).
//          Instance1 connects to Instance4 and begins streaming video.
// (12) Initiator: handleFlashAnswer() -> fmo2.prepareForCall()
//          The Responder's JS controller passes the peerID for Instance3 (Responder Sender) to Instance2
//          Instance2 prepares to receive video from Instance3
// (9) Initiator: fmo2.onCall():
//          Instance2 begins playing video from Instance3.
// (13) Responder: fmo4.onCall():
//          Instance4 begins playing video from Instance1

不高兴,但很高兴知道。通读这些文档,还不清楚,但是如果LocalConnection使用了与ExternalInterface类不同的封送机制,我会感到惊讶。不过我会查一查的。对于让这个场景正常工作的其他建议仍然持开放态度。ExternalInterface通过向DOM添加一些javascript方法来工作,这就是将对象封送到XML的地方。考虑到只有一个Flash Player进程运行所有SWF,在SWF之间通信时,它们可能根本不需要封送数据。如果我做得正确(这是一个重要的警告),我认为LocalConnection类将无法工作。下面是我得到的错误:
error#2044:未处理的AsyncErrorEvent:。text=错误#2095:flash.net.LocalConnection无法调用回调setCamera。error=TypeError:error#1034:类型强制失败:无法转换Object@dd20b81flash.media.Camera.
Hmm,看来我的假设是错的。通过LocalConnection发送的对象使用AMF协议进行(或可以?)序列化/反序列化。这似乎使这更容易做到,但事实上,它被反序列化为AMF意味着接收方必须创建一个相同类型的新对象。这适用于简单类(VO、DTO等),但可能不适用于表示系统上设备的本机Flash类(即摄像头和麦克风)。对于误导性的建议,我很抱歉:(无论如何,谢谢你的帮助。我正在研究一种不同的方法,包括让一个实例将视频广播到远程客户端,另一个实例接收视频。如果我能做到这一点(看起来很复杂),我将更新这个问题。