Google Meet Media API की मदद से, आपका ऐप्लिकेशन Google Meet कॉन्फ़्रेंस में शामिल हो सकता है. साथ ही, रीयल-टाइम मीडिया स्ट्रीम का इस्तेमाल कर सकता है.
क्लाइंट, Meet सर्वर से कम्यूनिकेट करने के लिए WebRTC का इस्तेमाल करते हैं. दिए गए रेफ़रंस क्लाइंट (C++, TypeScript) में, सुझाई गई सबसे सही प्रक्रियाओं के बारे में बताया गया है. हमारा सुझाव है कि आप सीधे तौर पर इनका इस्तेमाल करें.
हालांकि, आपके पास पूरी तरह से कस्टम WebRTC क्लाइंट बनाने का विकल्प भी होता है. ये क्लाइंट, Meet Media API की तकनीकी
ज़रूरतों के मुताबिक होने चाहिए.
इस पेज पर, Meet Media API सेशन को सही तरीके से इस्तेमाल करने के लिए ज़रूरी WebRTC के मुख्य कॉन्सेप्ट के बारे में बताया गया है.
ऑफ़र-आंसर सिग्नलिंग
WebRTC एक पीयर-टू-पीयर (P2P) फ़्रेमवर्क है. इसमें पीयर, एक-दूसरे को सिग्नल भेजकर कम्यूनिकेट करते हैं. सेशन शुरू करने के लिए, सेशन शुरू करने वाला पीयर, रिमोट पीयर को SDP
ऑफ़र भेजता है. इस ऑफ़र में यह अहम जानकारी शामिल है:
ऑडियो और वीडियो के लिए मीडिया के ब्यौरे
मीडिया के ब्यौरे से पता चलता है कि पी2पी सेशन के दौरान क्या कम्यूनिकेट किया जाता है. जानकारी तीन तरह की होती है: ऑडियो, वीडियो, और डेटा.
ऑफ़र देने वाला व्यक्ति या कंपनी, ऑफ़र में n ऑडियो स्ट्रीम दिखाने के लिए, n ऑडियो मीडिया के ब्यौरे शामिल करती है. वीडियो के लिए भी यही बात लागू होती है. हालांकि, ज़्यादा से ज़्यादा एक डेटा मीडिया ब्यौरा होगा.
दिशा
हर ऑडियो या वीडियो की जानकारी में, सिक्योर रीयल-टाइम ट्रांसपोर्ट प्रोटोकॉल (एसआरटीपी) की अलग-अलग स्ट्रीम के बारे में बताया जाता है. इन स्ट्रीम को RFC
3711 कंट्रोल करता है. ये दोनों तरफ़ से काम करते हैं. इसलिए, दो पीयर एक ही कनेक्शन पर मीडिया भेज और पा सकते हैं.
इस वजह से, हर मीडिया ब्यौरे (ऑफ़र और जवाब, दोनों में) में तीन में से एक एट्रिब्यूट होता है. इससे पता चलता है कि स्ट्रीम का इस्तेमाल कैसे किया जाना चाहिए:
sendonly: यह सिर्फ़ ऑफ़र करने वाले पीयर से मीडिया भेजता है. रिमोट पीयर, इस स्ट्रीम पर मीडिया नहीं भेजेगा.
recvonly: यह सिर्फ़ रिमोट पीयर से मीडिया हासिल करता है. ऑफ़र करने वाला व्यक्ति, इस स्ट्रीम पर मीडिया नहीं भेजेगा.
sendrecv: दोनों पीयर, इस स्ट्रीम पर डेटा भेज और पा सकते हैं.
कोडेक
हर मीडिया ब्यौरे में, उन कोडेक के बारे में भी बताया जाता है जिन्हें पीयर इस्तेमाल कर सकता है. Meet Media API के मामले में, क्लाइंट के ऑफ़र तब तक अस्वीकार कर दिए जाते हैं, जब तक वे तकनीकी ज़रूरी शर्तों में बताए गए कोडेक के साथ काम नहीं करते.
डीटीएलएस हैंडशेक
एसआरटीपी स्ट्रीम को सुरक्षित रखने के लिए, पीयर के बीच शुरुआती डेटाग्राम ट्रांसपोर्ट लेयर सिक्योरिटी ("DTLS", RFC
9147) हैंडशेक किया जाता है.
डीटीएलएस, क्लाइंट-टू-सर्वर प्रोटोकॉल है. सिग्नलिंग प्रोसेस के दौरान, एक पीयर सर्वर के तौर पर काम करता है, जबकि दूसरा पीयर के तौर पर काम करता है.
हर एसआरटीपी स्ट्रीम का अपना डीटीएलएस कनेक्शन हो सकता है. इसलिए, हर मीडिया ब्यौरे में तीन में से एक एट्रिब्यूट शामिल होता है. इससे डीटीएलएस हैंडशेक में पीयर की भूमिका के बारे में पता चलता है:
a=setup:actpass: ऑफ़र करने वाला पीयर, रिमोट पीयर की पसंद को प्राथमिकता देता है.
a=setup:active: यह पीयर, क्लाइंट के तौर पर काम करता है.
a=setup:passive: यह पीयर, सर्वर के तौर पर काम करता है.
ऐप्लिकेशन के मीडिया का ब्यौरा
डेटा चैनल (RFC 8831), स्ट्रीम कंट्रोल ट्रांसमिशन प्रोटोकॉल ("SCTP", RFC
9260) का ऐब्स्ट्रैक्शन है.
सिग्नलिंग के शुरुआती चरण के दौरान डेटा चैनल खोलने के लिए, ऑफ़र में ऐप्लिकेशन मीडिया की जानकारी शामिल होनी चाहिए. ऑडियो और वीडियो की जानकारी के उलट, ऐप्लिकेशन की जानकारी में दिशा या कोडेक के बारे में नहीं बताया जाता.
ICE के उम्मीदवार
किसी पीयर के इंटरैक्टिव कनेक्टिविटी इस्टैब्लिशमेंट ("ICE", RFC
8445) कैंडिडेट, उन रास्तों की सूची होते हैं जिनका इस्तेमाल कोई रिमोट पीयर, कनेक्शन बनाने के लिए कर सकता है.
दो पियर की सूचियों के कार्टेशियन प्रॉडक्ट को संभावित जोड़े कहा जाता है. यह दो पियर के बीच के संभावित रास्तों को दिखाता है. इन पेयर की जांच की जाती है, ताकि सबसे सही रास्ता तय किया जा सके.
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)
कनेक्शन फ़्लो का उदाहरण
ऑडियो मीडिया के बारे में जानकारी देने वाला ऑफ़र यहां दिया गया है:
पहली इमेज. ऑडियो मीडिया की जानकारी देने वाले ऑफ़र का उदाहरण.
रिमोट पीयर, मीडिया की जानकारी वाली लाइनों की उतनी ही संख्या के साथ एसडीपी जवाब देता है. हर लाइन से पता चलता है कि रिमोट पीयर, SRTP स्ट्रीम के ज़रिए ऑफ़र करने वाले क्लाइंट को कौनसी मीडिया फ़ाइल भेजता है. दूर मौजूद पीयर, ऑफ़र करने वाले व्यक्ति की कुछ स्ट्रीम को भी अस्वीकार कर सकता है. इसके लिए, वह मीडिया के ब्यौरे वाली एंट्री को recvonly पर सेट करता है.
Meet Media API के लिए, क्लाइंट हमेशा कनेक्शन शुरू करने के लिए एसडीपी ऑफ़र भेजते हैं. Meet कभी भी मीटिंग शुरू नहीं करता है.
इस व्यवहार को रेफ़रंस क्लाइंट (C++, TypeScript) मैनेज करते हैं. हालांकि, कस्टम क्लाइंट के डेवलपर, WebRTC के PeerConnectionInterface का इस्तेमाल करके ऑफ़र जनरेट कर सकते हैं.
Meet से कनेक्ट करने के लिए, ऑफ़र को कुछ ज़रूरी शर्तों का पालन करना होगा:
DTLS हैंडशेक में क्लाइंट को हमेशा क्लाइंट के तौर पर काम करना चाहिए. इसलिए, ऑफ़र में मौजूद हर मीडिया ब्यौरे में a=setup:actpass या a=setup:active में से किसी एक को तय करना होगा.
मीडिया के हर टाइप के लिए, मीडिया के ब्यौरे की हर लाइन में, ज़रूरी कोडेक इस्तेमाल किए जाने चाहिए:
ऑडियो:Opus
वीडियो:VP8, VP9, AV1
ऑडियो पाने के लिए, ऑफ़र में सिर्फ़ तीन ऑडियो मीडिया
डिटेल शामिल होनी चाहिए. इसके लिए, पीयर कनेक्शन ऑब्जेक्ट पर ट्रांससीवर सेट करें.
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'});
वीडियो पाने के लिए, ऑफ़र में सिर्फ़ वीडियो पाने के लिए इस्तेमाल होने वाले 1 से 3 मीडिया
ब्यौरे शामिल होने चाहिए. इसके लिए, पीयर कनेक्शन ऑब्जेक्ट पर ट्रांससीवर सेट करें.
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'});
ऑफ़र में हमेशा डेटा चैनल शामिल होने चाहिए. कम से कम session-control और media-stats चैनल हमेशा खुले होने चाहिए. सभी डेटा चैनल 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);};
एसडीपी ऑफ़र और जवाब का उदाहरण
यहां एसडीपी ऑफ़र और उससे मेल खाने वाले एसडीपी जवाब का पूरा उदाहरण दिया गया है. इस ऑफ़र में, ऑडियो और एक वीडियो स्ट्रीम के साथ Meet Media API सेशन के लिए बातचीत की जाती है.
देखें कि यहां तीन ऑडियो मीडिया के बारे में जानकारी दी गई है, एक वीडियो मीडिया के बारे में जानकारी दी गई है, और ऐप्लिकेशन मीडिया के बारे में ज़रूरी जानकारी दी गई है.