‘liusuyi’
2023-08-26 76817b8c752b12030ab285bcb5b2effebfa9a248
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import negotiateConnectionWithClientOffer from "./negotiateConnectionWithClientOffer.js";
/**
 * Example implementation of a client that uses WHEP to playback video over WebRTC
 *
 * https://www.ietf.org/id/draft-murillo-whep-00.html
 */
export default class WHEPClient {
    constructor(endpoint, videoElement) {
        this.endpoint = endpoint;
        this.videoElement = videoElement;
        this.stream = new MediaStream();
        /**
         * Create a new WebRTC connection, using public STUN servers with ICE,
         * allowing the client to disover its own IP address.
         * https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Protocols#ice
         */
        this.peerConnection = new RTCPeerConnection({
            iceServers: [
                {
                    urls: "stun:stun.cloudflare.com:3478",
                },
            ],
            bundlePolicy: "max-bundle",
        });
        /** https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/addTransceiver */
        this.peerConnection.addTransceiver("video", {
            direction: "recvonly",
        });
        this.peerConnection.addTransceiver("audio", {
            direction: "recvonly",
        });
        /**
         * When new tracks are received in the connection, store local references,
         * so that they can be added to a MediaStream, and to the <video> element.
         *
         * https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/track_event
         */
        this.peerConnection.ontrack = (event) => {
            const track = event.track;
            const currentTracks = this.stream.getTracks();
            const streamAlreadyHasVideoTrack = currentTracks.some(
                (track) => track.kind === "video"
            );
            const streamAlreadyHasAudioTrack = currentTracks.some(
                (track) => track.kind === "audio"
            );
            switch (track.kind) {
                case "video":
                    if (streamAlreadyHasVideoTrack) {
                        break;
                    }
                    this.stream.addTrack(track);
                    break;
                case "audio":
                    if (streamAlreadyHasAudioTrack) {
                        break;
                    }
                    this.stream.addTrack(track);
                    break;
                default:
                    console.log("got unknown track " + track);
            }
        };
        this.peerConnection.addEventListener("connectionstatechange", (ev) => {
            if (this.peerConnection.connectionState !== "connected") {
                return;
            }
            if (!this.videoElement.srcObject) {
                this.videoElement.srcObject = this.stream;
            }
        });
        this.peerConnection.addEventListener("negotiationneeded", (ev) => {
            negotiateConnectionWithClientOffer(this.peerConnection, this.endpoint);
        });
    }
}