你能在Flash实例之间传递Camera和Microphone对象吗?

时间:2012-12-27 18:59:00

标签: javascript flash webcam microphone

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

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

public class MediaController
{

    public function MediaController()
    {
        ExternalInterface.addCallback('getUserMedia', this.getUserMedia);
        ExternalInterface.addCallback('getCamera', this.getCamera);
        ExternalInterface.addCallback('setCamera', this.setCamera);
        ExternalInterface.addCallback('getMicrophone', this.getMicrophone);
        ExternalInterface.addCallback('setMicrophone', this.setMicrophone);
    }

    private var _mic:Microphone;
    private var _cam:Camera;

    public function getUserMedia()
    {
      _mic = Microphone.getMicrophone();
        _cam = Camera.getCamera();
    }

    public function getCamera():Camera
    {
        return this._cam;
    }

    public function setCamera(cam:Camera):void
    {
        this._cam = cam;
    }

    public function getMicrophone():Microphone
    {
        return this._mic;
    }

    public function setMicrophone(mic:Microphone):void
    {
        this._mic = mic;
    }
}

我会用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);

与这样做有关的任何已知陷阱?有没有更好的方法来处理这个? (在你问之前,是的,在没有其他建议的情况下,我打算对此进行编码,我会让每个人都知道我发现了什么 - 只是想知道在我得到之前是否有任何已知的陷阱或替代方案开始了。: - )

2 个答案:

答案 0 :(得分:1)

您无法通过CameraMicrophoneExternalInterface等对象传递给Javascript。当您使用ExternalInterface与Javascript通信时,您传递的任何数据都将编组为XML格式。所以在这一点上,相机/麦克风不再是Flash CameraMicrophone对象。

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

SWF可以使用LocalConnection课程相互通信,但我从未尝试使用相机或麦克风进行此类操作。

答案 1 :(得分:0)

对于它的价值,这是我最终采取的方法(或多或少),它的工作原理。复杂,有点脆,但它有效:

// 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