Tetap teratur dengan koleksi
Simpan dan kategorikan konten berdasarkan preferensi Anda.
Google Meet Media API memungkinkan aplikasi Anda bergabung ke konferensi Google Meet dan menggunakan streaming media real-time.
Klien menggunakan WebRTC untuk berkomunikasi dengan server Meet. Klien referensi yang disediakan (C++, TypeScript) menunjukkan praktik yang direkomendasikan dan Anda dianjurkan untuk membangun langsung di atasnya.
Namun, Anda juga dapat membuat klien WebRTC yang sepenuhnya kustom dan mematuhi persyaratan teknis Meet Media API.
Halaman ini menguraikan konsep utama WebRTC yang diperlukan untuk sesi Meet Media API yang berhasil.
Sinyal penawaran-jawaban
WebRTC adalah framework peer-to-peer (P2P), tempat peer berkomunikasi dengan saling memberi sinyal. Untuk memulai sesi, peer yang memulai mengirimkan penawaran
SDP ke peer jarak jauh. Penawaran ini mencakup detail penting berikut:
Deskripsi media untuk audio dan video
Deskripsi media menunjukkan apa yang dikomunikasikan selama sesi P2P. Ada tiga jenis deskripsi: audio, video, dan data.
Untuk menunjukkan aliran audio n, penawar menyertakan deskripsi media audio n
dalam penawaran. Hal yang sama berlaku untuk video. Namun, paling banyak hanya ada satu deskripsi media data.
Arah
Setiap deskripsi audio atau video menjelaskan setiap aliran Secure Real-time Transport Protocol (SRTP), yang diatur oleh RFC
3711. Koneksi ini bersifat dua arah, sehingga memungkinkan dua peer mengirim dan menerima media melalui koneksi yang sama.
Oleh karena itu, setiap deskripsi media (dalam penawaran dan jawaban) berisi
salah satu dari tiga atribut yang menjelaskan cara penggunaan streaming:
sendonly: Hanya mengirim media dari peer penawaran. Peer jarak jauh tidak akan mengirim media di streaming ini.
recvonly: Hanya menerima media dari peer jarak jauh. Peer yang menawarkan tidak akan mengirim media di aliran ini.
sendrecv: Kedua peer dapat mengirim dan menerima di aliran ini.
Codec
Setiap deskripsi media juga menentukan codec yang didukung peer. Dalam kasus Meet Media API, penawaran klien ditolak kecuali jika mendukung (setidaknya) codec yang ditentukan dalam persyaratan teknis.
Handshake DTLS
Streaming SRTP diamankan oleh handshake
Datagram Transport Layer Security ("DTLS", RFC
9147) awal antara peer.
DTLS biasanya merupakan protokol client-to-server; selama proses pensinyalan,
satu peer setuju untuk bertindak sebagai server, sementara peer lainnya bertindak sebagai peer.
Karena setiap aliran SRTP mungkin memiliki koneksi DTLS khusus, setiap
deskripsi media menentukan salah satu dari tiga atribut untuk menunjukkan peran peer
dalam handshake DTLS:
a=setup:actpass: Peer penawaran menunda pilihan peer
jarak jauh.
a=setup:active: Peer ini bertindak sebagai klien.
a=setup:passive: Peer ini bertindak sebagai server.
Deskripsi media aplikasi
Saluran data (RFC 8831) adalah
abstraksi dari Stream Control Transmission Protocol ("SCTP", RFC
9260).
Untuk membuka saluran data selama fase pemberian sinyal awal, penawaran harus berisi
deskripsi media aplikasi. Tidak seperti deskripsi audio dan video,
deskripsi aplikasi tidak menentukan arah atau codec.
Kandidat ICE
Kandidat Interactive Connectivity Establishment ("ICE", RFC
8445) peer adalah daftar rute yang dapat digunakan peer jarak jauh untuk membuat koneksi.
Produk kartesius dari daftar kedua peer, yang dikenal sebagai pasangan kandidat,
mewakili potensi rute antara dua peer. Pasangan ini diuji untuk
menentukan rute yang optimal.
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)
Contoh alur koneksi
Berikut adalah penawaran dengan deskripsi media audio:
Gambar 1. Contoh penawaran dengan deskripsi media audio.
Peer jarak jauh merespons dengan jawaban
SDP yang berisi jumlah baris deskripsi media yang sama. Setiap baris menunjukkan media apa, jika ada, yang dikirim kembali oleh peer jarak jauh ke klien penawaran melalui aliran SRTP. Peer jarak jauh
juga dapat menolak aliran tertentu dari penawar dengan menyetel entri deskripsi media tersebut ke recvonly.
Untuk Meet Media API, klien selalu mengirimkan penawaran SDP untuk memulai koneksi. Meet tidak pernah menjadi inisiator.
Perilaku ini dikelola secara internal oleh klien referensi
(C++, TypeScript),
tetapi developer klien kustom dapat menggunakan PeerConnectionInterface WebRTC untuk
membuat penawaran.
Untuk terhubung ke Meet Meet, penawaran harus mematuhi
persyaratan tertentu:
Klien harus selalu bertindak sebagai klien dalam handshake DTLS, sehingga setiap
deskripsi media dalam penawaran harus menentukan a=setup:actpass atau
a=setup:active.
Setiap baris deskripsi media harus mendukung semua codec yang diperlukan untuk jenis media tersebut:
Audio:Opus
Video:VP8, VP9, AV1
Untuk menerima audio, penawaran harus menyertakan tepat 3 deskripsi media audio hanya terima. Anda dapat melakukannya dengan menyetel transceiver pada objek koneksi peer.
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'});
Untuk menerima video, penawaran harus menyertakan 1–3 deskripsi media video hanya terima. Anda dapat melakukannya dengan menyetel transceiver pada objek koneksi peer.
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'});
Penawaran harus selalu menyertakan saluran data. Minimal, saluran
session-control dan media-stats harus selalu terbuka. Semua saluran data harus 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);};
Contoh penawaran dan jawaban SDP
Berikut adalah contoh lengkap penawaran SDP yang valid dan jawaban SDP yang cocok. Penawaran ini
menegosiasikan sesi Meet Media API dengan audio dan satu aliran
video.
Perhatikan bahwa ada tiga deskripsi media audio, satu deskripsi media video, dan deskripsi media aplikasi yang diperlukan.