ホームページ  >  記事  >  バックエンド開発  >  go-zero+WebRTCでリアルタイムビデオコミュニケーションを実現

go-zero+WebRTCでリアルタイムビデオコミュニケーションを実現

WBOY
WBOYオリジナル
2023-06-22 15:53:082132ブラウズ

ビデオ通信技術の発展に伴い、リアルタイムビデオ通信機能の実装を必要とするアプリケーションシナリオがますます増えています。 WebRTC は、ブラウザーとモバイル アプリケーションがリアルタイムで通信できるようにするオープン ソース プロジェクトであり、go-zero は、高パフォーマンスの Go 言語 Web サービスを迅速に構築するためのフレームワークです。この記事では、go-zeroとWebRTCを使ってリアルタイムビデオコミュニケーションを実現する方法を紹介します。

1. WebRTC の事前理解

WebRTC は、ブラウザとモバイル アプリケーション間のリアルタイム通信を可能にする Google のオープンソース プロジェクトであり、リアルタイムの音声およびビデオ通信とデータ送信機能を提供します。 。 WebRTC は、次のような一連のテクノロジーを使用してリアルタイム通信機能を実現します。

  1. TCP/UDP トランスポート プロトコル
  2. ICE (Interactive Connectivity establishment) テクノロジーを使用して、最適なパスを決定します。送信プロトコル
  3. SDP (セッション記述プロトコル) プロトコル。セッション プロセスの記述に使用されます。
  4. STUN (Session Traversal Utilities for NAT) プロトコル。NAT の検出とバイパスに使用されます。
  5. TURN (Traversal using Relays around NAT) プロトコルは、STUN

2 を使用して両端が接続できない場合に、送信にリレー サーバーを使用するために使用されます。

go-zero は、高パフォーマンスの Go 言語 Web サービスを迅速に構築するためのフレームワークです。次の特徴があります:

    RPC フレームワークに基づいており、複数のプロトコルをサポートします
  1. 高パフォーマンス、Sync.Pool およびメモリ プール テクノロジを使用します
  2. プラグイン、柔軟な拡張機能
  3. サポート ミドルウェア
  4. サポート API ゲートウェイ
3. go-zero と WebRTC を使用してリアルタイム ビデオ通信を実装します

In go- を使用するには、zero と WebRTC の間でリアルタイムのビデオ通信を実現するには、次の手順を完了する必要があります。

    go-zero の Web サービスを構築する
  1. シグナリング サーバーを実装するWebRTC の実装
  2. 実装 WebRTC のビデオ ストリーミング送信
  3. フロントエンド ページの実装
シグナリング サーバーは WebRTC の重要な部分であり、WebRTC の確立と確立に使用されます。ビデオ通信チャネルを維持します。 go-zero を使用してシグナリング サーバーを実装できます。まず、以下に示すように、関連する go-zero 依存関係パッケージをインポートする必要があります。

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"
)

次に、WebSocket プロトコル サーバーと対応するルーティング ハンドラーを実装できます。ルーティング ハンドラーの主な機能は、WebSocket 接続とデータ送信を処理し、シグナリング サーバーの基本機能を実装することです。コードは次のとおりです。

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)
}

上記のコードでは、websocket.Handler 関数を使用して WebSocket 接続リクエストを処理します。ここで、createHub 関数を使用してシグナル サーバーを表すハブ構造を作成します。 handleWebSocket 関数は、WebSocket 接続の読み取りおよび書き込み操作を処理するために使用されます。 handleMessage 関数は、さまざまな種類のシグナリング メッセージを処理するために使用されます。同時に、異なるクライアント間の接続を維持するために、ハブ構造を作成し、register、unregister、broadcast などのパイプを使用してクライアント リストを維持し、クライアントが接続、切断、メッセージを送信するときに応答します。

次に、WebRTC のビデオ ストリーミング機能を実装する必要があります。 WebRTC では、ビデオ ストリームは PeerConnection オブジェクトを通じて送信されます。 RTCPeerConnection の CreateOffer メソッドを呼び出すことで、オファー シグナリング メッセージを生成し、別のピアに送信できます。オファー メッセージを処理した後、別のピアは RTCPeerConnection の CreateAnswer メソッドを呼び出し、応答メッセージを生成して送り返すことができます。最終的に、両当事者は、RTCPeerConnection の SetLocalDescription メソッドと SetRemoteDescription メソッドを通じて SDP 記述情報を相手に送信し、ビデオ通信チャネルを確立します。コードは次のとおりです。

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
}

上記のコードでは、generateOffer、handleOffer、および handleAnswer という 3 つの処理メソッドを定義します。 generateOffer は、オファー シグナリング メッセージを生成し、sdp.SessionDescription 型のオブジェクトを返すために使用されます。 handleOffer と handleAnswer は、それぞれオファー シグナリング メッセージとアンサー シグナリング メッセージを処理するために使用され、SetRemoteDescription メソッドと SetLocalDescription メソッドを通じてそれぞれの SDP 記述情報を設定します。

最後に、フロントエンド ページを実装し、WebRTC を介したビデオ ストリーミング機能を実装する必要があります。ここでは詳細には触れません。

概要

この記事では、go-zero と WebRTC を使用してリアルタイム ビデオ コミュニケーションを実装する方法を紹介します。最初に WebRTC の基礎知識を紹介し、次に go-zero を使用して WebRTC のシグナリング サーバーとビデオ ストリーミング機能を実装し、最後にフロントエンド ページを実装しました。上記の実践を通じて、WebRTC のコア技術を深く理解しただけでなく、迅速な Web サービス開発のための go-zero の使用方法も学びました。

以上がgo-zero+WebRTCでリアルタイムビデオコミュニケーションを実現の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。