【问题标题】:Can you pass Camera and Microphone objects between Flash instances?您可以在 Flash 实例之间传递 Camera 和 Microphone 对象吗?
【发布时间】:2012-12-27 18:58:59
【问题描述】:

我正在开发一个 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);

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

【问题讨论】:

    标签: javascript flash webcam microphone


    【解决方案1】:

    您不能通过ExternalInterfaceCameraMicrophone 等对象传递给Javascript。当您使用ExternalInterface 与 Javascript 进行通信时,您传递的任何数据都将被编组为 XML 格式。所以到那时,相机/麦克风不再是 Flash CameraMicrophone 对象。

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

    SWF 可以使用 LocalConnection 类相互通信,尽管我从未尝试过使用摄像头或麦克风进行类似的操作。

    【讨论】:

    • 无赖,但很高兴知道。通读文档,不清楚,但如果 LocalConnection 使用与 ExternalInterface 类不同的编组机制,我会感到惊讶。不过,我会检查一下。仍然愿意接受其他建议以使此方案发挥作用。
    • ExternalInterface 通过向 DOM 添加一些 javascript 方法来工作,这就是将对象编组为 XML 的地方。鉴于只有一个 Flash Player 进程运行所有 SWF,因此在 SWF 之间进行通信时,它们可能根本不需要编组数据。
    • 如果我做得正确——一个重要的警告——我认为 LocalConnection 类不会起作用。这是我得到的错误:Error #2044: Unhandled AsyncErrorEvent:. text=Error #2095: flash.net.LocalConnection was unable to invoke callback setCamera. error=TypeError: Error #1034: Type Coercion failed: cannot convert Object@dd20b81 to flash.media.Camera.
    • 嗯,看来我的假设是错误的。通过 LocalConnection 发送的对象使用 AMF 协议进行(或可以?)序列化/反序列化。这个library 似乎更容易做到这一点,但它被反序列化为 AMF 的事实意味着接收方必须创建一个相同类型的新对象。这适用于简单的类(VO、DTO 等),但对于代表系统上设备的本机 Flash 类(即:相机和麦克风)可能不太好。对不起,误导性的建议:(
    • 感谢您的帮助。我正在研究一种不同的方法,包括让一个实例将视频广播到远程客户端,而另一个实例接收它。如果我可以让它工作(看起来很复杂),我会更新这个问题。
    【解决方案2】:

    对于它的价值,这是我最终采用的方法(或多或少),它有效。复杂,而且有点脆,但很有效:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-09-17
      • 2016-11-23
      • 2018-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-17
      相关资源
      最近更新 更多