webRTC java桌面附加媒体轨道并正确使用它们

zin*_*yar 8 java desktop-application webrtc

我正在尝试使用此webRTC Java 本机接口实现在两个 Java 应用程序之间构建对等音频传输,并使用带有套接字的简单 nodejs 服务器来执行信令,尽管无法获取音轨,但我可以建立连接工作,尝试添加轨道,添加收发器,将 audioDeviceModule 传递给 PeerConnectionFactory,但没有任何效果,我只想从呼叫者附加麦克风轨道并让它在另一侧正常播放。

我目前尝试连接音频:

    AudioDeviceModule mod = new AudioDeviceModule();
    mod.setRecordingDevice(MediaDevices.getAudioCaptureDevices().get(1));
    mod.initRecording();
    mod.setPlayoutDevice(MediaDevices.getAudioRenderDevices().get(1));
    mod.initPlayout();
    PeerConnectionFactory factory = new PeerConnectionFactory(mod);
    RTCPeerConnection connection = factory.createPeerConnection(config, observer);
    AudioOptions audioOptions = new AudioOptions();
    AudioSource audioSource = factory.createAudioSource(audioOptions);
    AudioTrack audioTrack = factory.createAudioTrack("audioTrack", audioSource);
    connection.addTrack(audioTrack, List.of("stream"));
Run Code Online (Sandbox Code Playgroud)

他们的 repo 上提供的演示很复杂,它没有帮助我理解 API,一个简单的“入门”示例会有所帮助。

到目前为止我所拥有的:结构是基本的 我正在运行两个 java 实例,通过套接字从第一个实例向服务器发送报价,服务器将其转发到第二个实例,后者设置远程描述并发送答案到服务器,服务器将其转发给第一个实例,该实例设置远程描述

呼叫者:

connection.createOffer(options, new CreateSessionDescriptionObserver() {
    @Override
    public void onSuccess(RTCSessionDescription description) {
        connection.setLocalDescription(description, new SetSessionDescriptionObserver() {
            @Override
            public void onSuccess() {
                System.out.println("caller ready");
            }

            @Override
            public void onFailure(String error) {
                System.out.println("failed to set local description : " + error);
            }
        });
     
        //Sending offer as a json object to the server
        JSONObject data = new JSONObject();
        JSONObject offer = new JSONObject();
        offer.put("sdp", description.sdp);
        offer.put("type", description.sdpType);
        data.put("offer", offer);
        data.put("to", socketId);
        mySocket.emit("call-user", data.toString());
        System.out.println("offer sent to " + socketId);

        //Listening for answer events
        mySocket.on("answer-made", e -> {
            JSONObject obj = (JSONObject) e[0];
            String sdp = obj.getJSONObject("answer").getString("sdp");
            System.out.println("received answer from " + obj.getString("socket"));
            connection.setRemoteDescription(new RTCSessionDescription(RTCSdpType.ANSWER, sdp),
                    new SetSessionDescriptionObserver() {
                        @Override
                        public void onSuccess() {
                            System.out.println("Connection Successful");
                        }

                        @Override
                        public void onFailure(String error) {
                            System.out.println("failed to set remote description : " + error);
                        }
                    });
        });
    }

    @Override
    public void onFailure(String error) {
        System.out.println("failed to create offer: " + error);
    }
});
Run Code Online (Sandbox Code Playgroud)

被叫方:

socket.on("call-made", e -> {
    JSONObject obj = (JSONObject) e[0];
    String sdp = obj.getJSONObject("offer").getString("sdp");
    String from = obj.getString("socket");
    System.out.println("received offer from " + from);

    RTCSessionDescription offer = new RTCSessionDescription(RTCSdpType.OFFER, sdp);
    connection.setRemoteDescription(offer, new SetSessionDescriptionObserver() {
        @Override
        public void onSuccess() {
            connection.createAnswer(options, new CreateSessionDescriptionObserver() {
                @Override
                public void onSuccess(RTCSessionDescription description) {
                    connection.setLocalDescription(description, new SetSessionDescriptionObserver() {
                        @Override
                        public void onSuccess() {
                            JSONObject data = new JSONObject();
                            JSONObject answer = new JSONObject();
                            answer.put("sdp", description.sdp);
                            answer.put("type", description.sdpType);
                            data.put("answer", answer);
                            data.put("to", socketId);
                            System.out.println("answer sent to " + socketId);

                            mySocket.emit("make-answer", data.toString());

                            System.out.println("Peer2Peer Connection Successful");
                        }

                        @Override
                        public void onFailure(String error) {
                            System.out.println("failed to set local description : " + error);
                        }
                    });
                }

                @Override
                public void onFailure(String error) {
                    System.out.println("failed to create answer : " + error);
                }
            });
        }

        @Override
        public void onFailure(String error) {
            System.out.println("failed to set remote description : " + error);
        }
    });
});
Run Code Online (Sandbox Code Playgroud)

服务器除了将提议/答案转发到另一个套接字之外什么都不做

连接设置正确,我得到以下输出,没有失败

呼叫者:

connecting to server...
connected, connection id : 7rO5KeRKQQjmGBiRAAAB
offer
enter id to call
nVlQRjwWsoPrM63uAAAA
offer sent to nVlQRjwWsoPrM63uAAAA
caller ready
received answer from nVlQRjwWsoPrM63uAAAA
Peer2Peer Connection Successful
Run Code Online (Sandbox Code Playgroud)

被叫方:

connecting to server...
connected, connection id : nVlQRjwWsoPrM63uAAAA
received offer from 7rO5KeRKQQjmGBiRAAAB
answer sent to 7rO5KeRKQQjmGBiRAAAB
Peer2Peer Connection Successful
Run Code Online (Sandbox Code Playgroud)