-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.go
117 lines (95 loc) · 2.73 KB
/
main.go
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package main
import (
"fmt"
"io"
"math/rand"
"net/http"
"strings"
"time"
"github.com/pion/webrtc/v4"
"github.com/pion/webrtc/v4/pkg/media"
"github.com/pion/webrtc/v4/pkg/media/oggwriter"
)
func saveToDisk(i media.Writer, track *webrtc.TrackRemote) {
defer func() {
if err := i.Close(); err != nil {
panic(err)
}
}()
for {
rtpPacket, _, err := track.ReadRTP()
if err != nil {
fmt.Println(err)
return
}
if err := i.WriteRTP(rtpPacket); err != nil {
fmt.Println(err)
return
}
}
}
func doSignaling(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Headers", "*")
if r.Method == "OPTIONS" {
return
}
offer, err := io.ReadAll(r.Body)
if err != nil {
panic(err)
}
peerConnection, err := webrtc.NewPeerConnection(webrtc.Configuration{})
if err != nil {
panic(err)
}
peerConnection.OnTrack(func(track *webrtc.TrackRemote, receiver *webrtc.RTPReceiver) { //nolint: revive
if strings.EqualFold(track.Codec().MimeType, webrtc.MimeTypeOpus) {
fileName := randString(10) + ".ogg"
fmt.Println("Got Opus track, saving to disk as " + fileName + " (48 kHz, 2 channels)")
oggFile, err := oggwriter.New(fileName, 48000, 2)
if err != nil {
panic(err)
}
saveToDisk(oggFile, track)
}
})
// Set the handler for ICE connection state
// This will notify you when the peer has connected/disconnected
peerConnection.OnICEConnectionStateChange(func(connectionState webrtc.ICEConnectionState) {
fmt.Printf("ICE Connection State has changed: %s\n", connectionState.String())
if connectionState == webrtc.ICEConnectionStateFailed {
peerConnection.Close()
}
})
if err = peerConnection.SetRemoteDescription(webrtc.SessionDescription{Type: webrtc.SDPTypeOffer, SDP: string(offer)}); err != nil {
panic(err)
}
// Create channel that is blocked until ICE Gathering is complete
gatherComplete := webrtc.GatheringCompletePromise(peerConnection)
answer, err := peerConnection.CreateAnswer(nil)
if err != nil {
panic(err)
} else if err = peerConnection.SetLocalDescription(answer); err != nil {
fmt.Println(answer.SDP)
panic(err)
}
<-gatherComplete
w.Header().Add("Location", "/")
w.WriteHeader(http.StatusCreated)
fmt.Fprint(w, peerConnection.LocalDescription().SDP)
}
func main() {
rand.Seed(time.Now().UnixNano()) //nolint
http.HandleFunc("/", doSignaling)
fmt.Println("Running WHIP server at http://localhost:8080")
// nolint: gosec
panic(http.ListenAndServe(":8085", nil))
}
var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
func randString(n int) string {
b := make([]rune, n)
for i := range b {
b[i] = letterRunes[rand.Intn(len(letterRunes))]
}
return string(b)
}