Zadbaj o dobrą organizację dzięki kolekcji
Zapisuj i kategoryzuj treści zgodnie ze swoimi preferencjami.
Interfejs Google Meet Media API umożliwia aplikacji dołączenie do konferencji w Google Meet i korzystanie ze strumieni multimediów w czasie rzeczywistym.
Klienci używają WebRTC do komunikacji z serwerami Meet. Dostarczone klienty referencyjne (C++, TypeScript) pokazują zalecane praktyki i zachęcamy do bezpośredniego korzystania z nich.
Możesz też jednak tworzyć w pełni niestandardowe klienty WebRTC, które spełniają wymagania techniczne interfejsu Meet Media API.
Na tej stronie znajdziesz najważniejsze pojęcia związane z WebRTC, które są niezbędne do prawidłowego działania sesji Meet Media API.
Sygnalizacja oferty i odpowiedzi
WebRTC to platforma peer-to-peer (P2P), w której urządzenia komunikują się ze sobą za pomocą sygnałów. Aby rozpocząć sesję, inicjujący węzeł wysyła do węzła zdalnego ofertę SDP. Ta oferta zawiera te ważne informacje:
Opisy multimediów w przypadku audio i wideo
Opisy multimediów wskazują, co jest przekazywane podczas sesji P2P. Istnieją 3 rodzaje opisów: audio, wideo i dane.
Aby wskazać n strumienie audio, oferujący umieszcza w ofercie n opisy multimediów audio. To samo dotyczy filmów. Może jednak być tylko jeden opis danych
multimedialnych.
Dozwolone kierunki jazdy
Każdy opis audio lub wideo opisuje poszczególne strumienie Secure Real-time Transport Protocol (SRTP), które podlegają RFC
3711. Są one dwukierunkowe, dzięki czemu 2 użytkowników może wysyłać i odbierać multimedia w ramach tego samego połączenia.
Dlatego każdy opis multimediów (zarówno w ofercie, jak i w odpowiedzi) zawiera jeden z 3 atrybutów opisujących sposób użycia strumienia:
sendonly: wysyła tylko multimedia od osoby, która złożyła ofertę. Urządzenie zdalne nie będzie wysyłać multimediów w tym strumieniu.
recvonly: odbiera tylko media od zdalnego peera. Oferujący nie będzie wysyłać multimediów w tym strumieniu.
sendrecv: obie strony mogą wysyłać i odbierać dane w tym strumieniu.
Kodeki
Każdy opis multimediów określa też kodeki obsługiwane przez urządzenie równorzędne. W przypadku interfejsu Meet Media API oferty klientów są odrzucane, chyba że obsługują (co najmniej) kodeki określone w wymaganiach technicznych.
Uzgadnianie połączenia DTLS
Strumienie SRTP są zabezpieczane przez początkowe uzgadnianie połączenia Datagram Transport Layer Security („DTLS”, RFC
9147) między urządzeniami.
DTLS jest tradycyjnie protokołem typu klient-serwer. Podczas procesu sygnalizacji jeden z elementów zgadza się pełnić rolę serwera, a drugi – rolę klienta.
Każdy strumień SRTP może mieć własne połączenie DTLS, dlatego każdy opis mediów określa jeden z 3 atrybutów, aby wskazać rolę urządzenia w uzgadnianiu połączenia DTLS:
a=setup:actpass: oferujący peer dostosowuje się do wyboru
zdalnego peera.
a=setup:active: ten węzeł pełni rolę klienta.
a=setup:passive: ten węzeł pełni rolę serwera.
Opisy multimediów aplikacji
Kanały danych (RFC 8831) to abstrakcja protokołu SCTP („SCTP”, RFC
9260).
Aby otworzyć kanały danych podczas początkowej fazy sygnalizacji, oferta musi zawierać opis multimediów aplikacji. W odróżnieniu od opisów audio i wideo opisy aplikacji nie określają kierunku ani kodeków.
Kandydaci ICE
Kandydaci Interactive Connectivity Establishment („ICE”, RFC
8445) to lista tras, których zdalny węzeł może użyć do nawiązania połączenia.
Iloczyn kartezjański list dwóch węzłów, zwany parami kandydatów, reprezentuje potencjalne trasy między dwoma węzłami. Te pary są testowane w celu określenia optymalnej trasy.
importcom.google.api.core.ApiFuture;importcom.google.apps.meet.v2beta.ConnectActiveConferenceRequest;importcom.google.apps.meet.v2beta.ConnectActiveConferenceResponse;importcom.google.apps.meet.v2beta.SpaceName;importcom.google.apps.meet.v2beta.SpacesServiceClient;publicclassAsyncConnectActiveConference{publicstaticvoidmain(String[]args)throwsException{asyncConnectActiveConference();}publicstaticvoidasyncConnectActiveConference()throwsException{// This snippet has been automatically generated and should be regarded as a code template only.// It will require modifications to work:// - It may require correct/in-range values for request initialization.// - It may require specifying regional endpoints when creating the service client as shown in// https://cloud.google.com/java/docs/setup#configure_endpoints_for_the_client_librarytry(SpacesServiceClientspacesServiceClient=SpacesServiceClient.create()){ConnectActiveConferenceRequestrequest=ConnectActiveConferenceRequest.newBuilder().setName(SpaceName.of("[SPACE]").toString()).setOffer("offer105650780").build();ApiFuture<ConnectActiveConferenceResponse>future=spacesServiceClient.connectActiveConferenceCallable().futureCall(request);// Do something.ConnectActiveConferenceResponseresponse=future.get();}}}
usingGoogle.Apps.Meet.V2Beta;usingSystem.Threading.Tasks;publicsealedpartialclassGeneratedSpacesServiceClientSnippets{/// <summary>Snippet for ConnectActiveConferenceAsync</summary>/// <remarks>/// This snippet has been automatically generated and should be regarded as a code template only./// It will require modifications to work:/// - It may require correct/in-range values for request initialization./// - It may require specifying regional endpoints when creating the service client as shown in/// https://cloud.google.com/dotnet/docs/reference/help/client-configuration#endpoint./// </remarks>publicasyncTaskConnectActiveConferenceAsync(){// Create clientSpacesServiceClientspacesServiceClient=awaitSpacesServiceClient.CreateAsync();// Initialize request argument(s)stringname="spaces/[SPACE]";// Make the requestConnectActiveConferenceResponseresponse=awaitspacesServiceClient.ConnectActiveConferenceAsync(name);}}
/** * This snippet has been automatically generated and should be regarded as a code template only. * It will require modifications to work. * It may require correct/in-range values for request initialization. * TODO(developer): Uncomment these variables before running the sample. *//** * Required. Resource name of the space. * Format: spaces/{spaceId} */// const name = 'abc123'/** * Required. WebRTC SDP (Session Description Protocol) offer from the client. * The format is defined by RFC * 8866 (https://www.rfc-editor.org/rfc/rfc8866) with mandatory keys defined * by RFC 8829 (https://www.rfc-editor.org/rfc/rfc8829). This is the standard * SDP format generated by a peer connection's createOffer() and * createAnswer() methods. */// const offer = 'abc123'// Imports the Meet libraryconst{SpacesServiceClient}=require('@google-apps/meet').v2beta;// Instantiates a clientconstmeetClient=newSpacesServiceClient();asyncfunctioncallConnectActiveConference(){// Construct requestconstrequest={name,offer,};// Run requestconstresponse=awaitmeetClient.connectActiveConference(request);console.log(response);}callConnectActiveConference();
# This snippet has been automatically generated and should be regarded as a# code template only.# It will require modifications to work:# - It may require correct/in-range values for request initialization.# - It may require specifying regional endpoints when creating the service# client as shown in:# https://googleapis.dev/python/google-api-core/latest/client_options.htmlfromgoogle.appsimportmeet_v2betaasyncdefsample_connect_active_conference():# Create a clientclient=meet_v2beta.SpacesServiceAsyncClient()# Initialize request argument(s)request=meet_v2beta.ConnectActiveConferenceRequest(name="name_value",offer="offer_value",)# Make the requestresponse=awaitclient.connect_active_conference(request=request)# Handle the responseprint(response)
Przykładowy przepływ połączenia
Oto oferta z opisem multimediów audio:
Rysunek 1. Przykładowa oferta z opisem multimedialnym w formacie audio.
Zdalny węzeł odpowiada odpowiedzią SDP zawierającą taką samą liczbę wierszy opisu multimediów. Każdy wiersz wskazuje, jakie media (jeśli w ogóle) zdalny peer wysyła z powrotem do klienta oferującego w strumieniach SRTP. Zdalny uczestnik może też odrzucić określone strumienie od oferującego, ustawiając wpis opisu multimediów na recvonly.
W przypadku interfejsu Meet Media API klienci zawsze wysyłają ofertę SDP, aby zainicjować połączenie. Meet nigdy nie jest inicjatorem.
To zachowanie jest zarządzane wewnętrznie przez klientów referencyjnych (C++, TypeScript), ale deweloperzy klientów niestandardowych mogą używać PeerConnectionInterface WebRTC do generowania oferty.
Aby połączyć się z Meet, oferta musi spełniać określone wymagania:
Klient musi zawsze pełnić rolę klienta w uzgadnianiu połączenia DTLS, więc każdy opis multimediów w ofercie musi określać a=setup:actpass lub a=setup:active.
Każda linia opisu multimediów musi obsługiwać wszystkie wymagane kodeki dla danego typu multimediów:
Dźwięk:Opus
Film:VP8, VP9, AV1
Aby otrzymywać dźwięk, oferta musi zawierać dokładnie 3 opisy multimediów audio tylko do odbioru. Możesz to zrobić, ustawiając nadajniki-odbiorniki w obiekcie połączenia równorzędnego.
C++
// ...rtc::scoped_refptr<webrtc::PeerConnectionInterface>peer_connection;for(inti=0;i < 3;++i){webrtc::RtpTransceiverInitaudio_init;audio_init.direction=webrtc::RtpTransceiverDirection::kRecvOnly;audio_init.stream_ids={absl::StrCat("audio_stream_",i)};webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>>
audio_result=peer_connection->AddTransceiver(cricket::MediaType::MEDIA_TYPE_AUDIO,audio_init);if(!audio_result.ok()){returnabsl::InternalError(absl::StrCat("Failed to add audio transceiver: ",audio_result.error().message()));}}
JavaScript
pc=newRTCPeerConnection();// Configure client to receive audio from Meet servers.pc.addTransceiver('audio',{'direction':'recvonly'});pc.addTransceiver('audio',{'direction':'recvonly'});pc.addTransceiver('audio',{'direction':'recvonly'});
Aby otrzymywać wideo, oferta musi zawierać 1–3 opisy multimediów wideo tylko do odbioru. Możesz to zrobić, ustawiając nadajniki-odbiorniki w obiekcie połączenia równorzędnego.
C++
// ...rtc::scoped_refptr<webrtc::PeerConnectionInterface>peer_connection;for(uint32_ti=0;i < configurations.receiving_video_stream_count;++i){webrtc::RtpTransceiverInitvideo_init;video_init.direction=webrtc::RtpTransceiverDirection::kRecvOnly;video_init.stream_ids={absl::StrCat("video_stream_",i)};webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>>
video_result=peer_connection->AddTransceiver(cricket::MediaType::MEDIA_TYPE_VIDEO,video_init);if(!video_result.ok()){returnabsl::InternalError(absl::StrCat("Failed to add video transceiver: ",video_result.error().message()));}}
JavaScript
pc=newRTCPeerConnection();// Configure client to receive video from Meet servers.pc.addTransceiver('video',{'direction':'recvonly'});pc.addTransceiver('video',{'direction':'recvonly'});pc.addTransceiver('video',{'direction':'recvonly'});
Oferta musi zawsze zawierać kanały danych. Zawsze powinny być otwarte co najmniej kanały session-control i media-stats. Wszystkie kanały danych muszą być w formacie ordered.
C++
// ...// All data channels must be ordered.constexprwebrtc::DataChannelInitkDataChannelConfig={.ordered=true};rtc::scoped_refptr<webrtc::PeerConnectionInterface>peer_connection;// Signal session-control data channel.webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::DataChannelInterface>>
session_create_result=peer_connection->CreateDataChannelOrError("session-control",&kDataChannelConfig);if(!session_create_result.ok()){returnabsl::InternalError(absl::StrCat("Failed to create data channel ",data_channel_label,": ",session_create_result.error().message()));}// Signal media-stats data channel.webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::DataChannelInterface>>
stats_create_result=peer_connection->CreateDataChannelOrError("media-stats",&kDataChannelConfig);if(!stats_create_result.ok()){returnabsl::InternalError(absl::StrCat("Failed to create data channel ",data_channel_label,": ",stats_create_result.error().message()));}
JavaScript
// ...pc=newRTCPeerConnection();// All data channels must be ordered.constdataChannelConfig={ordered:true,};// Signal session-control data channel.sessionControlChannel=pc.createDataChannel('session-control',dataChannelConfig);sessionControlChannel.onopen=()=>console.log("data channel is now open");sessionControlChannel.onclose=()=>console.log("data channel is now closed");sessionControlChannel.onmessage=async(e)=>{console.log("data channel message",e.data);};// Signal media-stats data channel.mediaStatsChannel=pc.createDataChannel('media-stats',dataChannelConfig);mediaStatsChannel.onopen=()=>console.log("data channel is now open");mediaStatsChannel.onclose=()=>console.log("data channel is now closed");mediaStatsChannel.onmessage=async(e)=>{console.log("data channel message",e.data);};
Przykładowa oferta i odpowiedź SDP
Oto pełny przykład prawidłowej oferty SDP i odpowiadającej jej odpowiedzi SDP. Ta oferta
negocjuje sesję interfejsu Meet Media API z dźwiękiem i pojedynczym strumieniem wideo.
Zwróć uwagę, że są 3 opisy multimediów audio, 1 opis multimediów wideo i wymagany opis multimediów aplikacji.
[[["Łatwo zrozumieć","easyToUnderstand","thumb-up"],["Rozwiązało to mój problem","solvedMyProblem","thumb-up"],["Inne","otherUp","thumb-up"]],[["Brak potrzebnych mi informacji","missingTheInformationINeed","thumb-down"],["Zbyt skomplikowane / zbyt wiele czynności do wykonania","tooComplicatedTooManySteps","thumb-down"],["Nieaktualne treści","outOfDate","thumb-down"],["Problem z tłumaczeniem","translationIssue","thumb-down"],["Problem z przykładami/kodem","samplesCodeIssue","thumb-down"],["Inne","otherDown","thumb-down"]],["Ostatnia aktualizacja: 2025-07-16 UTC."],[],[]]