-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cannot recieve Audio #2895
Comments
Okay so with a help of a friend I made a basic echo webRTC that works package webrtc
import (
"encoding/json"
"fmt"
"log"
"sync"
"time"
"github.com/gofiber/contrib/websocket"
"github.com/pion/rtcp"
"github.com/pion/webrtc/v3"
)
type Message struct {
Event string `json:"event"`
Data string `json:"data"`
}
type Client struct {
Id string
Conn *websocket.Conn
Pc *webrtc.PeerConnection
AudioTrack *webrtc.TrackLocalStaticRTP
}
var (
clients = make(map[string]*Client)
clientsMutex sync.Mutex
)
func Signaling(conn *websocket.Conn) {
clientID := fmt.Sprintf("client-%d", time.Now().UnixNano())
client := &Client{
Id: clientID,
Conn: conn,
}
clientsMutex.Lock()
clients[clientID] = client
clientsMutex.Unlock()
defer func() {
clientsMutex.Lock()
delete(clients, clientID)
clientsMutex.Unlock()
}()
for {
var msg Message
err := conn.ReadJSON(&msg)
if err != nil {
log.Println("Error reading message:", err)
return
}
switch msg.Event {
case "offer":
handleOffer(client, msg.Data)
case "candidate":
handleIceCandidate(client, msg.Data)
}
}
}
// handles the offer from the client!
func handleOffer(client *Client, offerString string) {
// Create a new RTCPeerConnection
config := webrtc.Configuration{
ICEServers: []webrtc.ICEServer{
{
URLs: []string{"stun:stun.l.google.com:19302"},
},
},
}
pc, err := webrtc.NewPeerConnection(config)
if err != nil {
log.Println(err)
return
}
client.Pc = pc
// Create an audio track
audioTrack, err := webrtc.NewTrackLocalStaticRTP(webrtc.RTPCodecCapability{MimeType: "audio/opus"}, "audio", "pion")
if err != nil {
log.Println(err)
return
}
client.AudioTrack = audioTrack
_, err = pc.AddTrack(audioTrack)
if err != nil {
log.Println(err)
return
}
// Sending an ICE candidate to the client
pc.OnICECandidate(func(c *webrtc.ICECandidate) {
if c == nil {
return
}
candidateString, err := json.Marshal(c.ToJSON())
if err != nil {
log.Println(err)
return
}
client.Conn.WriteJSON(Message{
Event: "candidate",
Data: string(candidateString),
})
})
// Checking the connection state at each step
pc.OnConnectionStateChange(func(s webrtc.PeerConnectionState) {
log.Printf("Client %s Peer Connection State has changed: %s\n", client.Id, s.String())
if s == webrtc.PeerConnectionStateFailed {
if err := pc.Close(); err != nil {
log.Println(err)
}
}
})
// Recveive the remote track from the client!
pc.OnTrack(func(remoteTrack *webrtc.TrackRemote, receiver *webrtc.RTPReceiver) {
log.Printf("Client %s new track: %d\n", client.Id, remoteTrack.SSRC())
go func() {
ticker := time.NewTicker(time.Second * 3)
for range ticker.C {
errSend := pc.WriteRTCP([]rtcp.Packet{&rtcp.PictureLossIndication{MediaSSRC: uint32(remoteTrack.SSRC())}})
if errSend != nil {
log.Println(errSend)
}
}
}()
for {
rtp, _, readErr := remoteTrack.ReadRTP()
if readErr != nil {
log.Println(readErr)
return
}
clientsMutex.Lock()
for _, c := range clients {
if writeErr := c.AudioTrack.WriteRTP(rtp); writeErr != nil {
log.Printf("Error writing RTP to client: %v\n", writeErr)
}
}
clientsMutex.Unlock()
}
})
// Set the remote SessionDescription
offer := webrtc.SessionDescription{}
if err := json.Unmarshal([]byte(offerString), &offer); err != nil {
log.Println(err)
return
}
if err := pc.SetRemoteDescription(offer); err != nil {
log.Println(err)
return
}
// Create answer
answer, err := pc.CreateAnswer(nil)
if err != nil {
log.Println(err)
return
}
// Set the local SessionDescription
if err := pc.SetLocalDescription(answer); err != nil {
log.Println(err)
return
}
// Send the answer
answerString, err := json.Marshal(answer)
if err != nil {
log.Println(err)
return
}
client.Conn.WriteJSON(Message{
Event: "answer",
Data: string(answerString),
})
}
// handles adding the ice candidate from the client!
func handleIceCandidate(client *Client, candidateString string) {
var candidate webrtc.ICECandidateInit
if err := json.Unmarshal([]byte(candidateString), &candidate); err != nil {
log.Println(err)
return
}
if err := client.Pc.AddICECandidate(candidate); err != nil {
log.Println(err)
}
} But I still don't know what I did wrong in my previous implementation other than making the client map since I was testing this out locally and just a single connection. lmk if anyone can help! |
The issue is you did AddTransceiver + AddTrack, so you are attempting to negotiate two transceivers. The second example only does an AddTrack. The WebRTC API with pairing of RTP Sender/Receiver is painful :( sorry I wasn't able to help sooner with this! If you run into more issues I am available at Slack and help out with issues a bit faster. thanks for using Pion! Hope your project went well :) |
Your environment.
What did you do?
I'm trying to get a basic example running using pion + gofiber. Where I just want to receive the audio from my browser and echo it back.
Here's the go code:
Here's the client js
What did you expect?
I expected that I would receive the audio but that was not the case
What happened?
All the connections happen i.e it gathers all the ICE candidates, accepts the offer and answer but the
OnTrack
method is only called once. I read in this issue that it is supposed to be called once but now my question is how do I invoke it again?Thank you for helping me out! Sorry for the noob question.
The text was updated successfully, but these errors were encountered: