Avec le développement de la technologie de communication vidéo, de plus en plus de scénarios d'application nécessitent des fonctions de communication vidéo en temps réel. WebRTC est un projet open source qui permet aux navigateurs et aux applications mobiles de communiquer en temps réel, et go-zero est un cadre permettant de créer rapidement des services Web en langage Go hautes performances. Cet article explique comment utiliser go-zero et WebRTC pour mettre en œuvre une communication vidéo en temps réel.
1. Compréhension préliminaire de WebRTC
WebRTC est un projet open source de Google qui permet une communication en temps réel entre les navigateurs et les applications mobiles. Il fournit des fonctions de communication audio et vidéo en temps réel. WebRTC utilise une série de technologies pour réaliser des fonctions de communication en temps réel, notamment :
2. Compréhension préliminaire de go-zero
go-zero est un cadre permettant de créer rapidement des services Web en langage Go hautes performances. Il présente les caractéristiques suivantes :
3. Utilisez go-zero et WebRTC pour réaliser une communication vidéo en temps réel
Afin d'utiliser go-zero et WebRTC pour réaliser une communication vidéo en temps réel, nous devons suivre les étapes suivantes :
Le serveur de signalisation est un élément clé de WebRTC et est utilisé pour établir et maintenir le canal de communication vidéo. Nous pouvons utiliser go-zero pour implémenter le serveur de signalisation. Tout d'abord, nous devons importer le package de dépendances go-zero approprié, comme indiqué ci-dessous :
import ( "bytes" "encoding/json" "github.com/creasty/defaults" "github.com/go-chi/chi/v5" "github.com/gorilla/websocket" "github.com/rs/zerolog" "github.com/rs/zerolog/log" "github.com/segmentio/ksuid" "math/rand" "net/http" "sync" "time" )
Ensuite, nous pouvons implémenter le serveur de protocole WebSocket et le gestionnaire de routage correspondant. La fonction principale du gestionnaire de routage est de gérer les connexions Websocket et la transmission de données, et de mettre en œuvre les fonctions de base du serveur de signalisation. Le code est le suivant :
type SignalServer struct { hub *Hub mu sync.Mutex } func NewSignalServer() *SignalServer { return &SignalServer{ hub: newHub(), } } func (s *SignalServer) routes() *chi.Mux { r := chi.NewRouter() r.Handle("/ws", websocket.Handler(s.handleWebSocket)) return r } func (s *SignalServer) handleWebSocket(conn *websocket.Conn) { sessionId := ksuid.New().String() client := &Client{ id: sessionId, conn: conn, send: make(chan []byte, 256), hub: s.hub, } s.hub.register <- client go client.writePump() for { _, message, err := conn.ReadMessage() if err != nil { break } s.handleMessage(client, message) } s.hub.unregister <- client conn.Close() } func (s *SignalServer) handleMessage(client *Client, data []byte) { log.Debug().Msgf("received message: %s", data) message := &SignalingMessage{} if err := json.Unmarshal(data, message); err != nil { log.Error().Msgf("failed to unmarshal data: %s", err.Error()) return } switch message.Type { case "register": s.handleRegister(client, message) case "offer": s.hub.broadcast <- &MessageData{ SenderId: client.id, Type: "offer", Payload: message.Payload, } case "answer": s.hub.broadcast <- &MessageData{ SenderId: client.id, Type: "answer", Payload: message.Payload, } case "candidate": s.hub.broadcast <- &MessageData{ SenderId: client.id, Type: "candidate", Payload: message.Payload, } default: log.Error().Msgf("unknown message type: %s", message.Type) } } func (s *SignalServer) handleRegister(client *Client, message *SignalingMessage) { room := message.Payload s.mu.Lock() defer s.mu.Unlock() if _, ok := s.hub.rooms[room]; !ok { s.hub.rooms[room] = make(map[string]*Client) } s.hub.rooms[room][client.id] = client log.Debug().Msgf("client %s registered in room %s", client.id, room) }
Dans le code ci-dessus, nous traitons les demandes de connexion WebSocket via la fonction websocket.Handler, où la fonction createHub est utilisée pour créer une structure hub représentant le serveur de signaux. La fonction handleWebSocket est utilisée pour gérer les opérations de lecture et d'écriture des connexions Websocket. La fonction handleMessage est utilisée pour gérer différents types de messages de signalisation. Dans le même temps, afin de maintenir les connexions entre les différents clients, nous avons créé une structure de hub et utilisé des pipelines tels que l'enregistrement, la désinscription et la diffusion pour maintenir la liste des clients et répondre lorsque le client se connecte, se déconnecte et envoie des messages.
Ensuite, nous devons implémenter la fonction de streaming vidéo de WebRTC. Dans WebRTC, les flux vidéo sont transmis via des objets PeerConnection. Nous pouvons générer un message de signalisation d'offre et l'envoyer à un autre homologue en appelant la méthode CreateOffer de RTCPeerConnection. Après avoir traité le message d'offre, un autre homologue peut appeler la méthode CreateAnswer de RTCPeerConnection, générer un message de réponse et le renvoyer. Finalement, les deux parties enverront leurs informations de description SDP à l'autre partie via les méthodes SetLocalDescription et SetRemoteDescription de RTCPeerConnection pour établir un canal de communication vidéo. Le code est le suivant :
func (p *Peer) generateOffer() (*sdp.SessionDescription, error) { offer, err := p.pconn.CreateOffer(nil) if err != nil { return nil, err } if err := p.pconn.SetLocalDescription(offer); err != nil { return nil, err } return offer, nil } func (p *Peer) handleOffer(payload string) (*sdp.SessionDescription, error) { offer, err := webrtc.NewSessionDescription(sdp.SessionDescriptionProtocolType, payload) if err != nil { return nil, err } if err := p.pconn.SetRemoteDescription(offer); err != nil { return nil, err } answer, err := p.pconn.CreateAnswer(nil) if err != nil { return nil, err } if err := p.pconn.SetLocalDescription(answer); err != nil { return nil, err } return answer, nil } func (p *Peer) handleAnswer(payload string) error { answer, err := webrtc.NewSessionDescription(sdp.SessionDescriptionProtocolType, payload) if err != nil { return err } if err := p.pconn.SetRemoteDescription(answer); err != nil { return err } return nil }
Dans le code ci-dessus, nous définissons trois méthodes de traitement : generateOffer, handleOffer et handleAnswer. generateOffer est utilisé pour générer un message de signalisation d'offre et renvoyer un objet de type sdp.SessionDescription. handleOffer et handleAnswer sont utilisés respectivement pour traiter les messages de signalisation d'offre et de réponse et définir leurs informations de description SDP respectives via les méthodes SetRemoteDescription et SetLocalDescription.
Enfin, nous devons implémenter la page frontale et implémenter la fonction de streaming vidéo via WebRTC. Je n’entrerai pas dans les détails ici.
Résumé
Cet article présente comment utiliser go-zero et WebRTC pour mettre en œuvre une communication vidéo en temps réel. Nous avons d'abord présenté les connaissances de base de WebRTC, puis utilisé go-zero pour implémenter les fonctions de serveur de signalisation et de streaming vidéo de WebRTC, et enfin implémenté la page frontale. Grâce aux pratiques ci-dessus, nous avons non seulement acquis une compréhension approfondie de la technologie de base de WebRTC, mais nous avons également appris à utiliser go-zero pour le développement rapide de services Web.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!