Aramalar sırasında video yönetme
Azure İletişim Hizmetleri SDK'ları ile görüntülü aramaları yönetmeyi öğrenin. Arama içinde video alma ve göndermeyi yönetmeyi öğreneceğiz.
Önkoşullar
- Etkin aboneliği olan bir Azure hesabı. Ücretsiz hesap oluşturun.
- Dağıtılan bir İletişim Hizmetleri kaynağı. İletişim Hizmetleri kaynağı oluşturun.
- Çağıran istemciyi etkinleştirmek için kullanıcı erişim belirteci. Daha fazla bilgi için bkz . Erişim belirteçleri oluşturma ve yönetme.
- İsteğe bağlı: Uygulamanıza sesli çağrı eklemek için hızlı başlangıcı tamamlayın
SDK’yı yükleyin
npm install
JavaScript için Azure İletişim Hizmetleri Common ve Calling SDK'sını yüklemek için komutunu kullanın:
npm install @azure/communication-common --save
npm install @azure/communication-calling --save
Gerekli nesneleri başlatma
CallClient
Çoğu çağrı işlemi için bir örnek gereklidir. Yeni CallClient
bir örnek oluşturduğunuzda, örneği gibi Logger
özel seçeneklerle yapılandırabilirsiniz.
örneğiyleCallClient
, çağrısı createCallAgent
yaparak bir CallAgent
örnek oluşturabilirsiniz. Bu yöntem zaman uyumsuz olarak bir CallAgent
örnek nesnesi döndürür.
createCallAgent
yöntemi bağımsız değişken olarak kullanırCommunicationTokenCredential
. Kullanıcı erişim belirtecini kabul eder.
öğesine erişmek deviceManager
için örnekteki CallClient
yöntemini kullanabilirsinizgetDeviceManager
.
const { CallClient } = require('@azure/communication-calling');
const { AzureCommunicationTokenCredential} = require('@azure/communication-common');
const { AzureLogger, setLogLevel } = require("@azure/logger");
// Set the logger's log level
setLogLevel('verbose');
// Redirect log output to console, file, buffer, REST API, or whatever location you want
AzureLogger.log = (...args) => {
console.log(...args); // Redirect log output to console
};
const userToken = '<USER_TOKEN>';
callClient = new CallClient(options);
const tokenCredential = new AzureCommunicationTokenCredential(userToken);
const callAgent = await callClient.createCallAgent(tokenCredential, {displayName: 'optional Azure Communication Services user name'});
const deviceManager = await callClient.getDeviceManager()
Microsoft altyapısına SDK bağlantısını en iyi şekilde yönetme
Örnek, Call Agent
çağrıları yönetmenize yardımcı olur (aramalara katılmak veya çağrıları başlatmak için). Arama SDK'nızın çalışması için gelen aramaların bildirimlerini almak ve diğer arama ayrıntılarını koordine etmek için Microsoft altyapısına bağlanması gerekir. Sizin iki olası durumu vardır Call Agent
:
Bağlı - Call Agent
connectionStatue değeri Connected
, istemci SDK'sının bağlı olduğu ve Microsoft altyapısından bildirim alabilen olduğu anlamına gelir.
Bağlantısı kesildi - Call Agent
Durumların Disconnected
connectionStatue değeri, SDK'nın düzgün bağlanmasını engelleyen bir sorun var. Call Agent
yeniden oluşturulmalıdır.
invalidToken
: Belirtecin süresi dolduysa veya geçersizCall Agent
örnekse bu hatayla bağlantı kesilir.connectionIssue
: İstemcinin Microsoft infrascture'a bağlanmasıyla ilgili bir sorun varsa, birçok yeniden denemedenCall Agent
sonra hata ortayaconnectionIssue
çıkar.
Özelliğin geçerli değerini connectionState
inceleyerek yerel Call Agent
bilgisayarınızın Microsoft altyapısına bağlı olup olmadığını denetleyebilirsiniz. Etkin bir çağrı sırasında, Bağlı durumundan connectionStateChanged
Bağlantısız duruma gelen değişikliklerin olup olmadığını Call Agent
belirlemek için olayı dinleyebilirsiniz.
const connectionState = callAgentInstance.connectionState;
console.log(connectionState); // it may return either of 'Connected' | 'Disconnected'
const connectionStateCallback = (args) => {
console.log(args); // it will return an object with oldState and newState, each of having a value of either of 'Connected' | 'Disconnected'
// it will also return reason, either of 'invalidToken' | 'connectionIssue'
}
callAgentInstance.on('connectionStateChanged', connectionStateCallback);
Cihaz yönetimi
Arama SDK'sı ile video kullanmaya başlamak için cihazları yönetebilmeniz gerekir. Cihazlar, Ses ve Görüntü'leri aramaya nelerin ilettiğini denetlemenize olanak tanır.
deviceManager
ile ses ve video akışlarınızı bir aramada iletebilecek yerel cihazları numaralandırabilirsiniz. Yerel cihazın mikrofonlarına ve kameralarına erişim izni istemek için de kullanabilirsiniz deviceManager
.
yöntemini çağırarak callClient.getDeviceManager()
erişebilirsinizdeviceManager
:
const deviceManager = await callClient.getDeviceManager();
Yerel cihazları alma
Yerel cihazlara erişmek için ve numaralandırma yöntemlerini getCameras()
getMicrophones
kullanabilirsinizdeviceManager
. Bu yöntemler zaman uyumsuz eylemlerdir.
// Get a list of available video devices for use.
const localCameras = await deviceManager.getCameras(); // [VideoDeviceInfo, VideoDeviceInfo...]
// Get a list of available microphone devices for use.
const localMicrophones = await deviceManager.getMicrophones(); // [AudioDeviceInfo, AudioDeviceInfo...]
// Get a list of available speaker devices for use.
const localSpeakers = await deviceManager.getSpeakers(); // [AudioDeviceInfo, AudioDeviceInfo...]
Varsayılan cihazları ayarlama
Hangi cihazların kullanabildiğini öğrendikte mikrofon, hoparlör ve kamera için varsayılan cihazları ayarlayabilirsiniz. İstemci varsayılanları ayarlanmamışsa, İletişim Hizmetleri SDK'sı işletim sistemi varsayılanlarını kullanır.
Mikrofon
Kullanılan cihaza erişme
// Get the microphone device that is being used.
const defaultMicrophone = deviceManager.selectedMicrophone;
Kullanılacak cihazı ayarlama
// Set the microphone device to use.
await deviceManager.selectMicrophone(localMicrophones[0]);
Hoparlör
Kullanılan cihaza erişme
// Get the speaker device that is being used.
const defaultSpeaker = deviceManager.selectedSpeaker;
Kullanılacak cihazı ayarlama
// Set the speaker device to use.
await deviceManager.selectSpeaker(localSpeakers[0]);
Kamera
Kullanılan cihaza erişme
// Get the camera device that is being used.
const defaultSpeaker = deviceManager.selectedSpeaker;
Kullanılacak cihazı ayarlama
// Set the speaker device to use.
await deviceManager.selectSpeaker(localCameras[0]);
Her CallAgent
biri kendi mikrofonunu ve ilişkili DeviceManager
hoparlörlerini seçebilir. Farklı CallAgents
mikrofonlar ve hoparlörler kullanmanızı öneririz. Aynı mikrofonları veya hoparlörleri paylaşmamalıdır. Paylaşım gerçekleşirse, Mikrofon Kullanıcıya Yönelik Tanılama tetiklenebilir ve tarayıcıya / işletim sistemine bağlı olarak mikrofon çalışmayı durdurabilir.
Yerel video akışı
Bir çağrıda video gönderebilmek için bir LocalVideoStream
nesne oluşturmanız gerekir.
const localVideoStream = new LocalVideoStream(camera);
Parametre olarak geçirilen kamera, yöntemi tarafından deviceManager.getCameras()
döndürülen nesnelerden biridirVideoDeviceInfo
.
A LocalVideoStream
aşağıdaki özelliklere sahiptir:
source
: Cihaz bilgileri.
const source = localVideoStream.source;
mediaStreamType
: ,ScreenSharing
veyaRawMedia
olabilirVideo
.
const type: MediaStreamType = localVideoStream.mediaStreamType;
Yerel kamera önizlemesi
yerel kameranızdan akış işlemeye başlamak için ve VideoStreamRenderer
kullanabilirsinizdeviceManager
.
Oluşturulduktan LocalVideoStream
sonra, ayarlamakVideoStreamRenderer
için bunu kullanın. VideoStreamRenderer
oluşturulduktan sonra, sayfanıza çocuk olarak ekleyebileceğiniz bir görünüm elde etmek için yöntemini çağırıncreateView()
.
Bu akış diğer katılımcılara gönderilmez; yerel bir önizleme akışıdır.
// To start viewing local camera preview
const cameras = await deviceManager.getCameras();
const camera = cameras[0];
const localVideoStream = new LocalVideoStream(camera);
const videoStreamRenderer = new VideoStreamRenderer(localVideoStream);
const view = await videoStreamRenderer.createView();
htmlElement.appendChild(view.target);
Yerel önizlemeyi durdurma
Yerel önizleme çağrısını durdurmak için öğesinden türetilen görünüme VideoStreamRenderer
atın.
VideoStreamRenderer atıldıktan sonra, önizlemenizi içeren DOM Düğümünden yöntemini çağırarak removeChild()
html ağacından görünümü kaldırın.
// To stop viewing local camera preview
view.dispose();
htmlElement.removeChild(view.target);
Kamera ve mikrofon için izin isteme
Bir uygulama izinler olmadan kamerayı veya mikrofonu kullanamaz. DeviceManager'ı kullanarak bir kullanıcıdan kamera ve/veya mikrofon izinleri vermesini isteyebilirsiniz:
const result = await deviceManager.askDevicePermission({audio: true, video: true});
Söz çözümlendikten sonra yöntemi, ve video
izinlerinin verilip verilmediğini audio
gösteren bir DeviceAccess
nesneyle birlikte döndürür:
console.log(result.audio);
console.log(result.video);
Notlar
videoDevicesUpdated
olay, video cihazları prize takılı/fişi takılıyken tetiklenir.audioDevicesUpdated
ses cihazları takılıyken olay tetiklenir.- DeviceManager oluşturulduğunda, ilk başta izinlerin henüz verilip verilmediğini bilmiyor, bu nedenle başlangıçta cihaz adı boştur ve ayrıntılı cihaz bilgileri içermez. Ardından DeviceManager.askPermission() API'sini çağırırsak kullanıcıdan cihaz erişimi istenir. Kullanıcı erişim izni vermek için 'izin ver' seçeneğini belirlediğinizde cihaz yöneticisi sistemdeki cihazlar hakkında bilgi edinir, cihaz listelerini güncelleştirir ve 'audioDevicesUpdated' ve 'videoDevicesUpdated' olaylarını yayar. Kullanıcı sayfayı yeniler ve bir cihaz yöneticisi oluşturursa, kullanıcı daha önce erişim verdiği için cihaz yöneticisi cihazlar hakkında bilgi edinir. Başlangıçta cihaz listeleri doldurulmuş ve 'audioDevicesUpdated' veya 'videoDevicesUpdated' olayları yaymaz.
- Konuşmacı numaralandırması/seçimi Android Chrome, iOS Safari veya macOS Safari'de desteklenmez.
Görüntülü kamera ile arama yerleştirme
Önemli
Şu anda yalnızca bir giden yerel video akışı desteklenmektedir.
Görüntülü arama yapmak için içindeki yöntemini deviceManager
kullanarak getCameras()
yerel kameraları listelemeniz gerekir.
Bir kamera seçtikten sonra örneği oluşturmak LocalVideoStream
için bu kamerayı kullanın.
bunu videoOptions
yöntemine CallAgent
startCall
dizi içinde localVideoStream
bir öğe olarak geçirin.
const deviceManager = await callClient.getDeviceManager();
const cameras = await deviceManager.getCameras();
const camera = cameras[0]
const localVideoStream = new LocalVideoStream(camera);
const placeCallOptions = {videoOptions: {localVideoStreams:[localVideoStream]}};
const userCallee = { communicationUserId: '<ACS_USER_ID>' }
const call = callAgent.startCall([userCallee], placeCallOptions);
- Ayrıca API ile görüntülü aramaya katılabilir ve API ile
CallAgent.join()
görüntülüCall.Accept()
aramayı kabul edebilir ve çağırabilirsiniz. - Aramanız bağlandığında, seçili kameradan diğer katılımcıya otomatik olarak bir video akışı göndermeye başlar.
Arama sırasında yerel video göndermeyi başlatma ve durdurma
Video başlatma
Arama sırasında video başlatmak için nesnedeki getCameras
deviceManager
yöntemini kullanarak kameraları listelemeniz gerekir.
Ardından istenen kamerayla yeni bir örneği LocalVideoStream
oluşturun ve nesneyi mevcut bir çağrı nesnesinin yöntemine startVideo
geçirinLocalVideoStream
:
const deviceManager = await callClient.getDeviceManager();
const cameras = await deviceManager.getCameras();
const camera = cameras[0]
const localVideoStream = new LocalVideoStream(camera);
await call.startVideo(localVideoStream);
Video durdur
Video göndermeye başarıyla başladıktan sonra, LocalVideoStream
arama örneğindeki localVideoStreams
koleksiyona bir tür Video
örneği eklenir.
Arama nesnesinde video akışını bulma
const localVideoStream = call.localVideoStreams.find( (stream) => { return stream.mediaStreamType === 'Video'} );
Yerel videoyu durdurma Arama sırasında yerel videoyu durdurmak için, video için kullanılan örneği öğesinin stopVideo yöntemine Call
geçirinlocalVideoStream
:
await call.stopVideo(localVideoStream);
Bu örneği çağırarak switchSource
etkin bir LocalVideoStream'e sahip olurken farklı bir kamera cihazına LocalVideoStream
geçebilirsiniz:
const cameras = await callClient.getDeviceManager().getCameras();
const camera = cameras[1];
localVideoStream.switchSource(camera);
Belirtilen video cihazı kullanılamıyorsa:
- Arama sırasında, videonuz kapalıysa ve kullanarak
call.startVideo()
video başlatırsanız, bu yöntem birSourceUnavailableError
oluşturur vecameraStartFailed
kullanıcıya yönelik tanılama true olarak ayarlanır. - yöntemine yapılan bir çağrı,
localVideoStream.switchSource()
true olarak ayarlanmasına neden olurcameraStartFailed
. Arama Tanılama kılavuzumuz, aramayla ilgili sorunları tanılama hakkında ek bilgiler sağlar.
Yerel videonun açık veya kapalı olduğunu doğrulamak için, true veya false döndüren yöntemini isLocalVideoStarted
kullanabilirsinizCall
:
// Check if local video is on or off
call.isLocalVideoStarted;
Yerel videoda yapılan değişiklikleri dinlemek için isLocalVideoStartedChanged olayına abone olabilir ve aboneliği kaldırabilirsiniz:
// Subscribe to local video event
call.on('isLocalVideoStartedChanged', () => {
// Callback();
});
// Unsubscribe from local video event
call.off('isLocalVideoStartedChanged', () => {
// Callback();
});
Arama sırasında ekran paylaşımını başlatma ve durdurma
Çağrı sırasında ekran paylaşımını başlatmak için bir nesnede Call
zaman uyumsuz yöntemini startScreenSharing()
kullanabilirsiniz:
Ekran paylaşımını başlatma
// Start screen sharing
await call.startScreenSharing();
Not: Ekran paylaşımı gönderme işlemi yalnızca masaüstü tarayıcılarında desteklenir.
LocalVideoStream koleksiyonunda ekran paylaşımını bulma
Ekran paylaşımını başarıyla göndermeye başladıktan sonra, arama örneğindeki koleksiyona localVideoStreams
türündeki ScreenSharing
bir LocalVideoStream
örnek eklenir.
const localVideoStream = call.localVideoStreams.find( (stream) => { return stream.mediaStreamType === 'ScreenSharing'} );
Ekran paylaşımını durdur
Arama sırasında ekran paylaşımını durdurmak için zaman uyumsuz API stoptScreenSharing kullanabilirsiniz:
// Stop screen sharing
await call.stopScreenSharing();
Ekran paylaşımı durumunu denetleme
Ekran paylaşımının açık veya kapalı olduğunu doğrulamak için true veya false döndüren isScreenSharingOn API'sini kullanabilirsiniz:
// Check if screen sharing is on or off
call.isScreenSharingOn;
Ekran paylaşımındaki değişiklikleri dinlemek için isScreenSharingOnChanged olayına abone olabilir ve aboneliği kaldırabilirsiniz:
// Subscribe to screen share event
call.on('isScreenSharingOnChanged', () => {
// Callback();
});
// Unsubscribe from screen share event
call.off('isScreenSharingOnChanged', () => {
// Callback();
});
Önemli
Azure İletişim Hizmetleri'nin bu özelliği şu anda önizleme aşamasındadır.
Önizleme API'leri ve SDK'ları hizmet düzeyi sözleşmesi olmadan sağlanır. Bunları üretim iş yükleri için kullanmamanızı öneririz. Bazı özellikler desteklenmeyebilir veya kısıtlı özelliklere sahip olabilir.
Daha fazla bilgi için Microsoft Azure Önizlemeleri için Ek Kullanım Koşulları'nı gözden geçirin.
Yerel ekran paylaşımı önizlemesi genel önizleme aşamasındadır ve sürüm 1.15.1-beta.1+ kapsamında kullanılabilir.
Yerel ekran paylaşımı önizlemesi
Ekran paylaşım akışı olarak ne gönderdiğinizi görebilmek için yerel ekran paylaşımınızdan akışları işlemeye başlamak için bir VideoStreamRenderer
kullanabilirsiniz.
// To start viewing local screen share preview
await call.startScreenSharing();
const localScreenSharingStream = call.localVideoStreams.find( (stream) => { return stream.mediaStreamType === 'ScreenSharing' });
const videoStreamRenderer = new VideoStreamRenderer(localScreenSharingStream);
const view = await videoStreamRenderer.createView();
htmlElement.appendChild(view.target);
// To stop viewing local screen share preview.
await call.stopScreenSharing();
view.dispose();
htmlElement.removeChild(view.target);
// Screen sharing can also be stoped by clicking on the native browser's "Stop sharing" button.
// The isScreenSharingOnChanged event will be triggered where you can check the value of call.isScreenSharingOn.
// If the value is false, then that means screen sharing is turned off and so we can go ahead and dispose the screen share preview.
// This event is also triggered for the case when stopping screen sharing via Call.stopScreenSharing() API.
call.on('isScreenSharingOnChanged', () => {
if (!call.isScreenSharingOn) {
view.dispose();
htmlElement.removeChild(view.target);
}
});
Uzak katılımcı video/ekran paylaşımı akışlarını işleme
Uzak katılımcı videosunu veya ekran paylaşımını işlemek için ilk adım, işlemek istediğiniz RemoteVideoStream üzerinde bir başvuru almaktır.
Bu işlem, dizininden veya video akışından RemoteParticipant
(videoStreams
) geçirilerek yapılabilir. Uzak katılımcılar koleksiyonuna Call
nesnesi aracılığıyla erişilir.
const remoteVideoStream = call.remoteParticipants[0].videoStreams[0];
const streamType = remoteVideoStream.mediaStreamType;
işlemek RemoteVideoStream
için olayına isAvailableChanged
abone olmanız gerekir. isAvailable
özelliği olarak true
değişirse, uzak katılımcı bir video akışı gönderir.
Bundan sonra, yeni bir örneği VideoStreamRenderer
oluşturun ve ardından zaman uyumsuz createView
yöntemini kullanarak yeni VideoStreamRendererView
bir örnek oluşturun.
Daha sonra herhangi bir kullanıcı arabirimi öğesine ekleyebilirsiniz view.target
.
Uzak akışın kullanılabilirliği her değiştiğinde, tamamını VideoStreamRenderer
veya belirli VideoStreamRendererView
bir öğesini yok edebilirsiniz.
Bunları saklamaya karar verirseniz, görünüm boş bir video çerçevesi görüntüler.
// Reference to the html's div where we would display a grid of all remote video stream from all participants.
let remoteVideosGallery = document.getElementById('remoteVideosGallery');
subscribeToRemoteVideoStream = async (remoteVideoStream) => {
let renderer = new VideoStreamRenderer(remoteVideoStream);
let view;
let remoteVideoContainer = document.createElement('div');
remoteVideoContainer.className = 'remote-video-container';
let loadingSpinner = document.createElement('div');
// See the css example below for styling the loading spinner.
loadingSpinner.className = 'loading-spinner';
remoteVideoStream.on('isReceivingChanged', () => {
try {
if (remoteVideoStream.isAvailable) {
const isReceiving = remoteVideoStream.isReceiving;
const isLoadingSpinnerActive = remoteVideoContainer.contains(loadingSpinner);
if (!isReceiving && !isLoadingSpinnerActive) {
remoteVideoContainer.appendChild(loadingSpinner);
} else if (isReceiving && isLoadingSpinnerActive) {
remoteVideoContainer.removeChild(loadingSpinner);
}
}
} catch (e) {
console.error(e);
}
});
const createView = async () => {
// Create a renderer view for the remote video stream.
view = await renderer.createView();
// Attach the renderer view to the UI.
remoteVideoContainer.appendChild(view.target);
remoteVideosGallery.appendChild(remoteVideoContainer);
}
// Remote participant has switched video on/off
remoteVideoStream.on('isAvailableChanged', async () => {
try {
if (remoteVideoStream.isAvailable) {
await createView();
} else {
view.dispose();
remoteVideosGallery.removeChild(remoteVideoContainer);
}
} catch (e) {
console.error(e);
}
});
// Remote participant has video on initially.
if (remoteVideoStream.isAvailable) {
try {
await createView();
} catch (e) {
console.error(e);
}
}
console.log(`Initial stream size: height: ${remoteVideoStream.size.height}, width: ${remoteVideoStream.size.width}`);
remoteVideoStream.on('sizeChanged', () => {
console.log(`Remote video stream size changed: new height: ${remoteVideoStream.size.height}, new width: ${remoteVideoStream.size.width}`);
});
}
Uzak video akışı üzerinden yükleme değiştiricisini şekillendirmek için CSS.
.remote-video-container {
position: relative;
}
.loading-spinner {
border: 12px solid #f3f3f3;
border-radius: 50%;
border-top: 12px solid #ca5010;
width: 100px;
height: 100px;
-webkit-animation: spin 2s linear infinite; /* Safari */
animation: spin 2s linear infinite;
position: absolute;
margin: auto;
top: 0;
bottom: 0;
left: 0;
right: 0;
transform: translate(-50%, -50%);
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* Safari */
@-webkit-keyframes spin {
0% { -webkit-transform: rotate(0deg); }
100% { -webkit-transform: rotate(360deg); }
}
Uzak video kalitesi
Azure İletişim Hizmetleri WebJS SDK'sı, 1.15.1 sürümünden başlayarak En İyi Video Sayısı (OVC) adlı bir özellik sağlar.
Bu özellik, uygulamaları bir grup çağrısında (2+ katılımcı) belirli bir anda farklı katılımcılardan gelen kaç videoyu en iyi şekilde işleyebileceğiniz konusunda bilgilendirmek için kullanılabilir.
Bu özellik, yerel uç noktanın ağ ve donanım özelliklerine göre çağrı sırasında dinamik olarak değişen bir özelliği optimalVideoCount
kullanıma sunar. Değerinin optimalVideoCount
değeri, belirli bir anda farklı katılımcı uygulamasından kaç videonun işlenmesi gerektiğini açıklar. Uygulamalar bu değişiklikleri işlemeli ve işlenen video sayısını öneriye göre güncelleştirmelidir. Her güncelleştirme arasında bir ayırma süresi (yaklaşık 10 sn) vardır.
Kullanım Bu optimalVideoCount
özellik bir arama özelliğidir. Nesnenin yöntemi Call
aracılığıyla feature
özelliğe OptimalVideoCount
başvurmanız gerekir. Ardından optimalVideoCount değiştiğinde on
bildirim almak için yöntemini OptimalVideoCountCallFeature
kullanarak bir dinleyici ayarlayabilirsiniz. Değişikliklerin aboneliğini kaldırmak için yöntemini çağırabilirsiniz off
. İşlenebilen en fazla gelen video sayısı 16'dır. 16 gelen videoyu düzgün bir şekilde desteklemek için bilgisayarda 16 GB RAM'lik bir mimimum ve 3 yaşından eski olmayan 4 çekirdekli veya daha büyük bir CPU olmalıdır.
const optimalVideoCountFeature = call.feature(Features.OptimalVideoCount);
optimalVideoCountFeature.on('optimalVideoCountChanged', () => {
const localOptimalVideoCountVariable = optimalVideoCountFeature.optimalVideoCount;
})
Örnek kullanım: Uygulama, grup çağrılarında En uygun Video Sayısı değişikliklerine abone olmalıdır. En uygun video sayısındaki bir değişiklik, yeni işleyici (createView
yöntem) oluşturularak veya görünümleri atarak (dispose
) ve uygulama düzenini uygun şekilde güncelleştirerek işlenebilir.
Uzak video akışı özellikleri
Uzak video akışları aşağıdaki özelliklere sahiptir:
const id: number = remoteVideoStream.id;
id
: Uzak video akışının kimliği.
const type: MediaStreamType = remoteVideoStream.mediaStreamType;
mediaStreamType
: veyaScreenSharing
olabilirVideo
.
const isAvailable: boolean = remoteVideoStream.isAvailable;
isAvailable
: Uzak katılımcı uç noktasının etkin bir şekilde akış gönderip göndermediğini tanımlar.
const isReceiving: boolean = remoteVideoStream.isReceiving;
isReceiving
:Uzak video akışı verilerinin alındığını veya alınmadığını uygulamaya bildirir.
Bayrağı aşağıdaki senaryolarda 'a
false
taşınır:- Mobil tarayıcıdaki uzak katılımcı, tarayıcı uygulamasını arka plana getirir.
- Uzak bir katılımcı veya videoyu alan kullanıcının video kalitesini önemli ölçüde etkileyen ağ sorunu vardır.
- MacOS/iOS Safari'de olan uzak bir katılımcı, adres çubuğundan "Duraklat" seçeneğini seçer.
- Uzak katılımcının ağ bağlantısı kesiliyor.
- Mobil cihazlardaki uzak bir katılımcı tarayıcıyı öldürür veya sonlandırır.
- Mobil veya masaüstündeki uzak katılımcı cihazını kilitler. Bu senaryo, uzak katılımcı bir masaüstü bilgisayardaysa ve uyku moduna geçtiğinde de geçerlidir.
Bayrağı aşağıdaki senaryolarda 'a
true
taşınır:- Mobil tarayıcıda olan ve tarayıcısı arka planına sahip uzak bir katılımcı onu ön plana geri getirir.
- MacOS/iOS Safari'de olan uzak bir katılımcı, videosunu duraklatdıktan sonra adres çubuğundan "Sürdür"ü seçer.
- Uzak katılımcı, geçici bir bağlantı kesildikten sonra ağa yeniden bağlanır.
- Mobil cihazlardaki uzak bir katılımcı cihazının kilidini açar ve mobil tarayıcıdan aramaya geri döner.
Bu özellik, uzak video akışlarını işlemeye yönelik kullanıcı deneyimini geliştirir.
Bayrağı false olarak değiştirirse uzak video akışı üzerinden bir yükleme değiştirici görüntüleyebilirsiniz. Yükleme değiştiricisi uygulamanız gerekmez, ancak daha iyi bir kullanıcı deneyimi için en yaygın kullanım yük değiştiricidir.
const size: StreamSize = remoteVideoStream.size;
size
: Videonun genişliği ve yüksekliği hakkında bilgi içeren akış boyutu.
VideoStreamRenderer yöntemleri ve özellikleri
await videoStreamRenderer.createView();
Uzak video akışını işlemek için uygulama kullanıcı arabirimine eklenebilen createView()
bir VideoStreamRendererView
örnek oluşturun, zaman uyumsuz yöntemi kullanın, akış işlemeye hazır olduğunda çözümleniyor ve DOM ağacında herhangi bir yere eklenebilen öğeyi temsil video
eden özelliğe sahip target
bir nesne döndürüyor.
videoStreamRenderer.dispose();
videoStreamRenderer
ve tüm ilişkili VideoStreamRendererView
örnekleri atın.
VideoStreamRendererView yöntemleri ve özellikleri
Oluşturduğunuzda VideoStreamRendererView
ve isMirrored
özelliklerini belirtebilirsinizscalingMode
. scalingMode
, Crop
veya Fit
olabilirStretch
. Belirtilirse isMirrored
, işlenen akış dikey olarak çevrilmiş olur.
const videoStreamRendererView: VideoStreamRendererView = await videoStreamRenderer.createView({ scalingMode, isMirrored });
Her VideoStreamRendererView
örneğin işleme yüzeyini temsil eden bir target
özelliği vardır. Bu özelliği uygulama kullanıcı arabirimine ekleyin:
htmlElement.appendChild(view.target);
Yöntemini çağırarak updateScalingMode
güncelleştirebilirsinizscalingMode
:
view.updateScalingMode('Crop');
Aynı masaüstü cihazından aynı aramada iki farklı kameradan video akışları gönderin.
Önemli
Azure İletişim Hizmetleri'nin bu özelliği şu anda önizleme aşamasındadır.
Önizleme API'leri ve SDK'ları hizmet düzeyi sözleşmesi olmadan sağlanır. Bunları üretim iş yükleri için kullanmamanızı öneririz. Bazı özellikler desteklenmeyebilir veya kısıtlı özelliklere sahip olabilir.
Daha fazla bilgi için Microsoft Azure Önizlemeleri için Ek Kullanım Koşulları'nı gözden geçirin.
Aynı çağrıda iki farklı kameradan video akışı gönderme, masaüstü tarafından desteklenen tarayıcılarda sürüm 1.17.1-beta.1+ kapsamında desteklenir.
- Aynı çağrıda, aşağıdaki kod parçacığıyla tek bir masaüstü tarayıcı sekmesinden/uygulamasından iki farklı kameradan video akışı gönderebilirsiniz:
// Create your first CallAgent with identity A
const callClient1 = new CallClient();
const callAgent1 = await callClient1.createCallAgent(tokenCredentialA);
const deviceManager1 = await callClient1.getDeviceManager();
// Create your second CallAgent with identity B
const callClient2 = new CallClient();
const callAgent2 = await callClient2.createCallAgent(tokenCredentialB);
const deviceManager2 = await callClient2.getDeviceManager();
// Join the call with your first CallAgent
const camera1 = await deviceManager1.getCameras()[0];
const callObj1 = callAgent1.join({ groupId: ‘123’}, { videoOptions: { localVideoStreams: [new LocalVideoStream(camera1)] } });
// Join the same call with your second CallAgent and make it use a different camera
const camera2 = (await deviceManager2.getCameras()).filter((camera) => { return camera !== camera1 })[0];
const callObj2 = callAgent2.join({ groupId: '123' }, { videoOptions: { localVideoStreams: [new LocalVideoStream(camera2)] } });
//Mute the microphone and speakers of your second CallAgent’s Call, so that there is no echos/noises.
await callObj2.muteIncomingAudio();
await callObj2.mute();
Sınırlamalar:
- Bunun farklı kimlikler kullanılarak iki farklı
CallAgent
örnekle yapılması gerekir. Kod parçacığı, her biri kendi Call nesnesine sahip iki çağrı aracısının kullanıldığını gösterir. - Kod örneğinde, her iki CallAgents da aynı çağrıya (aynı çağrı kimlikleri) katılıyor. Ayrıca her aracıyla farklı aramalara katılabilir ve bir aramada bir video, diğer aramada ise farklı bir video gönderebilirsiniz.
- Aynı kamerayı her iki CallAgent'da da gönderme desteklenmez. İki farklı kamera olmalı.
- Bir CallAgent ile iki farklı kamera göndermek şu anda desteklenmiyor.
- macOS Safari'de, arka plan bulanıklaştırma video efektleri (uygulamasından @azure/communication-effects), hem aynı anda hem de tek bir kameraya uygulanabilir.
SDK’yı yükleyin
Proje düzeyi build.gradle
dosyanızı bulun ve ve allprojects
altındaki buildscript
depolar listesine ekleyinmavenCentral()
:
buildscript {
repositories {
...
mavenCentral()
...
}
}
allprojects {
repositories {
...
mavenCentral()
...
}
}
Ardından modül düzeyi build.gradle
dosyanızda bölümüne aşağıdaki satırları dependencies
ekleyin:
dependencies {
...
implementation 'com.azure.android:azure-communication-calling:1.0.0'
...
}
Gerekli nesneleri başlatma
Örnek CallAgent
oluşturmak için bir örnekte yöntemini CallClient
çağırmanız createCallAgent
gerekir. Bu çağrı zaman uyumsuz olarak bir CallAgent
örnek nesnesi döndürür.
createCallAgent
yöntemi, bir erişim belirtecini kapsülleyen bir bağımsız değişken olarak alırCommunicationUserCredential
.
öğesine erişmek DeviceManager
için önce bir callAgent
örnek oluşturmanız gerekir. Ardından almak için DeviceManager
yöntemini kullanabilirsinizCallClient.getDeviceManager
.
String userToken = '<user token>';
CallClient callClient = new CallClient();
CommunicationTokenCredential tokenCredential = new CommunicationTokenCredential(userToken);
android.content.Context appContext = this.getApplicationContext(); // From within an activity, for instance
CallAgent callAgent = callClient.createCallAgent(appContext, tokenCredential).get();
DeviceManager deviceManager = callClient.getDeviceManager(appContext).get();
Çağıranın görünen adını ayarlamak için şu alternatif yöntemi kullanın:
String userToken = '<user token>';
CallClient callClient = new CallClient();
CommunicationTokenCredential tokenCredential = new CommunicationTokenCredential(userToken);
android.content.Context appContext = this.getApplicationContext(); // From within an activity, for instance
CallAgentOptions callAgentOptions = new CallAgentOptions();
callAgentOptions.setDisplayName("Alice Bob");
DeviceManager deviceManager = callClient.getDeviceManager(appContext).get();
CallAgent callAgent = callClient.createCallAgent(appContext, tokenCredential, callAgentOptions).get();
Cihaz yönetimi
Arama ile video kullanmaya başlamak için cihazları yönetmeyi bilmeniz gerekir. Cihazlar, Ses ve Görüntü'leri aramaya nelerin ilettiğini denetlemenize olanak tanır.
DeviceManager
, ses/video akışlarınızı iletmek için bir aramada kullanılabilecek yerel cihazları listelemenize olanak tanır. Ayrıca yerel tarayıcı API'sini kullanarak bir kullanıcıdan mikrofon ve kameraya erişim izni istemenizi sağlar.
yöntemini çağırarak callClient.getDeviceManager()
erişebilirsinizdeviceManager
.
Context appContext = this.getApplicationContext();
DeviceManager deviceManager = callClient.getDeviceManager(appContext).get();
Yerel cihazları listeleme
Yerel cihazlara erişmek için Aygıt Yöneticisi numaralandırma yöntemlerini kullanabilirsiniz. Numaralandırma zaman uyumlu bir eylemdir.
// Get a list of available video devices for use.
List<VideoDeviceInfo> localCameras = deviceManager.getCameras(); // [VideoDeviceInfo, VideoDeviceInfo...]
Yerel kamera önizlemesi
yerel kameranızdan akış işlemeye başlamak için ve Renderer
kullanabilirsinizDeviceManager
. Bu akış diğer katılımcılara gönderilmez; yerel bir önizleme akışıdır. Bu, zaman uyumsuz bir eylemdir.
VideoDeviceInfo videoDevice = <get-video-device>; // See the `Enumerate local devices` topic above
Context appContext = this.getApplicationContext();
LocalVideoStream currentVideoStream = new LocalVideoStream(videoDevice, appContext);
LocalVideoStream[] localVideoStreams = new LocalVideoStream[1];
localVideoStreams[0] = currentVideoStream;
VideoOptions videoOptions = new VideoOptions(localVideoStreams);
RenderingOptions renderingOptions = new RenderingOptions(ScalingMode.Fit);
VideoStreamRenderer previewRenderer = new VideoStreamRenderer(currentVideoStream, appContext);
VideoStreamRendererView uiView = previewRenderer.createView(renderingOptions);
// Attach the uiView to a viewable location on the app at this point
layout.addView(uiView);
Video kamera ile 1:1 araması yerleştirme
Uyarı
Şu anda yalnızca bir giden yerel video akışı desteklenmektedir Görüntülü arama yapmak için API'yi kullanarak deviceManager
getCameras
yerel kameraları listelemeniz gerekir.
İstediğiniz kamerayı seçtikten sonra bir örnek oluşturmak LocalVideoStream
ve bunu dizideki localVideoStream
bir öğe olarak bir call
yönteme videoOptions
geçirmek için kullanın.
Arama bağlandıktan sonra, seçilen kameradan diğer katılımcılara otomatik olarak bir video akışı göndermeye başlar.
Not
Gizlilikle ilgili endişelerden dolayı, yerel olarak önizlemesi yapılmadığı takdirde aramada video paylaşılmaz. Diğer ayrıntılar için bkz . Yerel kamera önizlemesi .
VideoDeviceInfo desiredCamera = <get-video-device>; // See the `Enumerate local devices` topic above
Context appContext = this.getApplicationContext();
LocalVideoStream currentVideoStream = new LocalVideoStream(desiredCamera, appContext);
LocalVideoStream[] localVideoStreams = new LocalVideoStream[1];
localVideoStreams[0] = currentVideoStream;
VideoOptions videoOptions = new VideoOptions(localVideoStreams);
// Render a local preview of video so the user knows that their video is being shared
Renderer previewRenderer = new VideoStreamRenderer(currentVideoStream, appContext);
View uiView = previewRenderer.createView(new CreateViewOptions(ScalingMode.FIT));
// Attach the uiView to a viewable location on the app at this point
layout.addView(uiView);
CommunicationUserIdentifier[] participants = new CommunicationUserIdentifier[]{ new CommunicationUserIdentifier("<acs user id>") };
StartCallOptions startCallOptions = new StartCallOptions();
startCallOptions.setVideoOptions(videoOptions);
Call call = callAgent.startCall(context, participants, startCallOptions);
Yerel video göndermeyi başlatma ve durdurma
Video başlatmak için nesne üzerindeki deviceManager
API'yi kullanarak getCameraList
kameraları listelemeniz gerekir. Ardından istenen kamerayı geçirmenin LocalVideoStream
yeni bir örneğini oluşturun ve api'de startVideo
bağımsız değişken olarak geçirin:
VideoDeviceInfo desiredCamera = <get-video-device>; // See the `Enumerate local devices` topic above
Context appContext = this.getApplicationContext();
LocalVideoStream currentLocalVideoStream = new LocalVideoStream(desiredCamera, appContext);
VideoOptions videoOptions = new VideoOptions(currentLocalVideoStream);
Future startVideoFuture = call.startVideo(appContext, currentLocalVideoStream);
startVideoFuture.get();
Video göndermeye başarıyla başladıktan sonra, çağrı örneğindeki localVideoStreams
koleksiyona bir LocalVideoStream
örnek eklenir.
List<LocalVideoStream> videoStreams = call.getLocalVideoStreams();
LocalVideoStream currentLocalVideoStream = videoStreams.get(0); // Please make sure there are VideoStreams in the list before calling get(0).
Yerel videoyu durdurmak için koleksiyonda LocalVideoStream
localVideoStreams
bulunan örneği geçirin:
call.stopVideo(appContext, currentLocalVideoStream).get();
Bir örneği çağırarak switchSource
video gönderilirken farklı bir LocalVideoStream
kamera cihazına geçebilirsiniz:
currentLocalVideoStream.switchSource(source).get();
Uzak katılımcı video akışlarını işleme
Uzak katılımcıların video akışlarını ve ekran paylaşım akışlarını listelemek için koleksiyonları videoStreams
inceleyin:
List<RemoteParticipant> remoteParticipants = call.getRemoteParticipants();
RemoteParticipant remoteParticipant = remoteParticipants.get(0); // Please make sure there are remote participants in the list before calling get(0).
List<RemoteVideoStream> remoteStreams = remoteParticipant.getVideoStreams();
RemoteVideoStream remoteParticipantStream = remoteStreams.get(0); // Please make sure there are video streams in the list before calling get(0).
MediaStreamType streamType = remoteParticipantStream.getType(); // of type MediaStreamType.Video or MediaStreamType.ScreenSharing
Uzak katılımcıdan RemoteVideoStream
bir iş oluşturmak için bir OnVideoStreamsUpdated
olaya abone olmanız gerekir.
Olay içinde özelliğin isAvailable
true olarak değiştirilmesi, uzak katılımcının şu anda bir akış gönderdiğini gösterir. Bu durumda, yeni bir Renderer
örneği oluşturun ve zaman uyumsuz API kullanarak yeni RendererView
bir oluşturun ve uygulamanızın createView
kullanıcı arabiriminde herhangi bir yere ekleyin view.target
.
Bir uzak akış kullanılabilirliği değiştiğinde, işleyicinin tamamını, belirli RendererView
bir veya bunları saklamayı seçebilirsiniz, ancak bu boş video çerçevesi görüntülenmesine neden olur.
VideoStreamRenderer remoteVideoRenderer = new VideoStreamRenderer(remoteParticipantStream, appContext);
VideoStreamRendererView uiView = remoteVideoRenderer.createView(new RenderingOptions(ScalingMode.FIT));
layout.addView(uiView);
remoteParticipant.addOnVideoStreamsUpdatedListener(e -> onRemoteParticipantVideoStreamsUpdated(p, e));
void onRemoteParticipantVideoStreamsUpdated(RemoteParticipant participant, RemoteVideoStreamsEvent args) {
for(RemoteVideoStream stream : args.getAddedRemoteVideoStreams()) {
if(stream.getIsAvailable()) {
startRenderingVideo();
} else {
renderer.dispose();
}
}
}
Uzak video akışı özellikleri
Uzak video akışının birkaç özelliği vardır
Id
- Uzak video akışının kimliği
int id = remoteVideoStream.getId();
MediaStreamType
- 'Video' veya 'ScreenSharing' olabilir
MediaStreamType type = remoteVideoStream.getMediaStreamType();
isAvailable
- Uzak katılımcı uç noktasının etkin bir şekilde akış gönderip göndermediğini gösterir
boolean availability = remoteVideoStream.isAvailable();
oluşturucu yöntemleri ve özellikleri
API'leri izleyen işleyici nesnesi
- Uzak video akışını işlemek için daha sonra uygulama kullanıcı arabirimine eklenebilen bir
VideoStreamRendererView
örnek oluşturun.
// Create a view for a video stream
VideoStreamRendererView.createView()
- Işleyiciyi ve bu işleyiciyle ilişkili tümünü
VideoStreamRendererView
at. Kullanıcı arabiriminden tüm ilişkili görünümleri kaldırdığınızda çağrılmak için.
VideoStreamRenderer.dispose()
StreamSize
- uzak video akışının boyutu (genişlik/yükseklik)
StreamSize renderStreamSize = VideoStreamRenderer.getSize();
int width = renderStreamSize.getWidth();
int height = renderStreamSize.getHeight();
RendererView yöntemleri ve özellikleri
OluştururkenVideoStreamRendererView
, bu görünüme uygulanacak ve mirrored
özelliklerini belirtebilirsinizScalingMode
: Ölçeklendirme modu 'CROP' modundan biri olabilir | 'FIT'
VideoStreamRenderer remoteVideoRenderer = new VideoStreamRenderer(remoteVideoStream, appContext);
VideoStreamRendererView rendererView = remoteVideoRenderer.createView(new CreateViewOptions(ScalingMode.Fit));
Oluşturulan RendererView daha sonra aşağıdaki kod parçacığı kullanılarak uygulama kullanıcı arabirimine eklenebilir:
layout.addView(rendererView);
Daha sonra ScalingMode.CROP | öğesinden biriyle RendererView nesnesindeki API'yi çağırarak updateScalingMode
ölçeklendirme modunu güncelleştirebilirsiniz Bağımsız değişken olarak ScalingMode.FIT.
// Update the scale mode for this view.
rendererView.updateScalingMode(ScalingMode.CROP)
Sisteminizi ayarlama
Sisteminizi ayarlamak için bu adımları izleyin.
Xcode projesini oluşturma
Xcode'da yeni bir iOS projesi oluşturun ve Tek Görünüm Uygulaması şablonunu seçin. Bu makalede SwiftUI çerçevesi kullanılır, bu nedenle Dil'i Swift olarak ve Arabirim'i SwiftUI olarak ayarlamanız gerekir.
Bu makalede testler oluşturacaksınız. Testleri Dahil Et onay kutusunu temizleyebilirsiniz.
CocoaPods kullanarak paketi ve bağımlılıkları yükleme
Uygulamanız için aşağıdaki örnekte olduğu gibi bir Podfile oluşturun:
platform :ios, '13.0' use_frameworks! target 'AzureCommunicationCallingSample' do pod 'AzureCommunicationCalling', '~> 1.0.0' end
pod install
'i çalıştırın.Xcode kullanarak açın
.xcworkspace
.
Mikrofona erişim isteme
Cihazın mikrofona erişmek için kullanarak uygulamanızın bilgi özellik listesini NSMicrophoneUsageDescription
güncelleştirmeniz gerekir. İlişkili değeri, sistemin kullanıcıdan erişim istemek için kullandığı iletişim kutusuna eklenmiş bir dizeye ayarlayın.
Proje ağacının Info.plist girdisine sağ tıklayın ve Kaynak Kodu Olarak>Aç'ı seçin. Üst düzey <dict>
bölüme aşağıdaki satırları ekleyin ve dosyayı kaydedin.
<key>NSMicrophoneUsageDescription</key>
<string>Need microphone access for VOIP calling.</string>
Uygulama çerçevesini ayarlama
Projenizin ContentView.swift
dosyasını açın. Kitaplığı içeri aktarmak AzureCommunicationCalling
için dosyanın en üstüne bir import
bildirim ekleyin. Buna ek olarak, içeri aktar.AVFoundation
Koddaki ses izni istekleri için buna ihtiyacınız vardır.
import AzureCommunicationCalling
import AVFoundation
CallAgent'ı başlatma
öğesinden CallClient
bir CallAgent
örnek oluşturmak için, başlatıldıktan sonra zaman uyumsuz olarak bir nesne döndüren bir CallAgent
yöntem kullanmanız callClient.createCallAgent
gerekir.
Çağrı istemcisi oluşturmak için bir CommunicationTokenCredential
nesne geçirin:
import AzureCommunication
let tokenString = "token_string"
var userCredential: CommunicationTokenCredential?
do {
let options = CommunicationTokenRefreshOptions(initialToken: token, refreshProactively: true, tokenRefresher: self.fetchTokenSync)
userCredential = try CommunicationTokenCredential(withOptions: options)
} catch {
updates("Couldn't created Credential object", false)
initializationDispatchGroup!.leave()
return
}
// tokenProvider needs to be implemented by Contoso, which fetches a new token
public func fetchTokenSync(then onCompletion: TokenRefreshOnCompletion) {
let newToken = self.tokenProvider!.fetchNewToken()
onCompletion(newToken, nil)
}
CommunicationTokenCredential
Oluşturduğunuz nesneyi öğesine CallClient
geçirin ve görünen adı ayarlayın:
self.callClient = CallClient()
let callAgentOptions = CallAgentOptions()
options.displayName = " iOS Azure Communication Services User"
self.callClient!.createCallAgent(userCredential: userCredential!,
options: callAgentOptions) { (callAgent, error) in
if error == nil {
print("Create agent succeeded")
self.callAgent = callAgent
} else {
print("Create agent failed")
}
})
Cihazları yönetme
Arama ile video kullanmaya başlamak için cihazları yönetmeyi bilmeniz gerekir. Cihazlar, Ses ve Görüntü'leri aramaya nelerin ilettiğini denetlemenize olanak tanır.
DeviceManager
, ses veya video akışlarını iletmek için bir çağrıda kullanılabilecek yerel cihazları listelemenize olanak tanır. Ayrıca bir kullanıcıdan mikrofona veya kameraya erişim izni istemenizi sağlar. Nesneye callClient
erişebilirsinizdeviceManager
.
self.callClient!.getDeviceManager { (deviceManager, error) in
if (error == nil) {
print("Got device manager instance")
self.deviceManager = deviceManager
} else {
print("Failed to get device manager instance")
}
}
Yerel cihazları listeleme
Yerel cihazlara erişmek için cihaz yöneticisinde numaralandırma yöntemlerini kullanabilirsiniz. Numaralandırma zaman uyumlu bir eylemdir.
// enumerate local cameras
var localCameras = deviceManager.cameras // [VideoDeviceInfo, VideoDeviceInfo...]
Yerel kamera önizlemesi alma
Yerel kameranızdan bir akışı işlemeye başlamak için kullanabilirsiniz Renderer
. Bu akış diğer katılımcılara gönderilmez; yerel bir önizleme akışıdır. Bu, zaman uyumsuz bir eylemdir.
let camera: VideoDeviceInfo = self.deviceManager!.cameras.first!
let localVideoStream = LocalVideoStream(camera: camera)
let localRenderer = try! VideoStreamRenderer(localVideoStream: localVideoStream)
self.view = try! localRenderer.createView()
Yerel kamera önizleme özelliklerini alma
oluşturucu, işlemeyi denetlemenize olanak sağlayan özellikler ve yöntemler kümesine sahiptir.
// Constructor can take in LocalVideoStream or RemoteVideoStream
let localRenderer = VideoStreamRenderer(localVideoStream:localVideoStream)
let remoteRenderer = VideoStreamRenderer(remoteVideoStream:remoteVideoStream)
// [StreamSize] size of the rendering view
localRenderer.size
// [VideoStreamRendererDelegate] an object you provide to receive events from this Renderer instance
localRenderer.delegate
// [Synchronous] create view
try! localRenderer.createView()
// [Synchronous] create view with rendering options
try! localRenderer!.createView(withOptions: CreateViewOptions(scalingMode: ScalingMode.fit))
// [Synchronous] dispose rendering view
localRenderer.dispose()
Görüntülü 1:1 araması yerleştirme
Cihaz yöneticisi örneği almak için cihazları yönetme bölümüne bakın.
let firstCamera = self.deviceManager!.cameras.first
self.localVideoStreams = [LocalVideoStream]()
self.localVideoStreams!.append(LocalVideoStream(camera: firstCamera!))
let videoOptions = VideoOptions(localVideoStreams: self.localVideoStreams!)
let startCallOptions = StartCallOptions()
startCallOptions.videoOptions = videoOptions
let callee = CommunicationUserIdentifier('UserId')
self.callAgent?.startCall(participants: [callee], options: startCallOptions) { (call, error) in
if error == nil {
print("Successfully started outgoing video call")
self.call = call
} else {
print("Failed to start outgoing video call")
}
}
Uzak katılımcı video akışlarını işleme
Uzak katılımcılar arama sırasında video veya ekran paylaşımı başlatabilir.
Uzak katılımcıların video paylaşımı veya ekran paylaşımı akışlarını işleme
Uzak katılımcıların akışlarını listelemek için koleksiyonları videoStreams
inceleyin.
var remoteParticipantVideoStream = call.remoteParticipants[0].videoStreams[0]
Uzak video akışı özelliklerini alma
var type: MediaStreamType = remoteParticipantVideoStream.type // 'MediaStreamTypeVideo'
var isAvailable: Bool = remoteParticipantVideoStream.isAvailable // indicates if remote stream is available
var id: Int = remoteParticipantVideoStream.id // id of remoteParticipantStream
Uzak katılımcı akışlarını işleme
Uzak katılımcı akışlarını işlemeye başlamak için aşağıdaki kodu kullanın.
let renderer = VideoStreamRenderer(remoteVideoStream: remoteParticipantVideoStream)
let targetRemoteParticipantView = renderer?.createView(withOptions: CreateViewOptions(scalingMode: ScalingMode.crop))
// To update the scaling mode later
targetRemoteParticipantView.update(scalingMode: ScalingMode.fit)
Uzak video işleyici yöntemlerini ve özelliklerini alma
// [Synchronous] dispose() - dispose renderer and all `RendererView` associated with this renderer. To be called when you have removed all associated views from the UI.
remoteVideoRenderer.dispose()
Sisteminizi ayarlama
Sisteminizi ayarlamak için bu adımları izleyin.
Visual Studio projesini oluşturma
Evrensel Windows Platformu bir uygulama için Visual Studio 2022'de yeni bir Boş Uygulama (Evrensel Windows) projesi oluşturun. Proje adını girdikten sonra, 10.0.17763.0'dan sonraki bir Windows SDK'sını seçebilirsiniz.
WinUI 3 uygulaması için, tek sayfalı bir WinUI 3 uygulaması ayarlamak için Boş Uygulama, Paketlenmiş (Masaüstünde WinUI 3) şablonuyla yeni bir proje oluşturun. Windows Uygulama SDK'sı sürüm 1.3 veya üzeri gereklidir.
NuGet Paket Yöneticisi kullanarak paketi ve bağımlılıkları yükleme
Arama SDK'sı API'leri ve kitaplıkları bir NuGet paketi aracılığıyla genel kullanıma sunulur.
Arama SDK'sı NuGet paketini bulmak, indirmek ve yüklemek için:
- Araçlar>NuGet Paket Yöneticisi Çözüm için NuGet Paketlerini Yönet'i seçerek NuGet Paket Yöneticisi> açın.
- Gözat'ı seçin ve arama kutusuna Azure.Communication.Calling.WindowsClient yazın.
- Ön sürümü dahil et onay kutusunun seçili olduğundan emin olun.
- Azure.Communication.Calling.WindowsClient paketini ve ardından Azure.Communication.Calling.WindowsClient 1.4.0-beta.1 veya daha yeni bir sürümü seçin.
- Sağ bölmedeki Azure İletişim Hizmetleri projeye karşılık gelen onay kutusunu seçin.
- Yükle'yi seçin.
Mikrofona erişim isteme
Uygulamanın düzgün çalışması için kameraya erişim gerekir. UWP uygulamalarında kamera özelliği, uygulama bildirim dosyasında bildirilmelidir.
Aşağıdaki adımlar bunun nasıl başarıldığını gösterir.
- Panelde
Solution Explorer
uzantılı.appxmanifest
dosyaya çift tıklayın. - Sekmeye
Capabilities
tıklayın. Camera
Yetenekler listesinden onay kutusunu seçin.
Aramayı yerleştirmek ve kapatmak için kullanıcı arabirimi düğmeleri oluşturma
Bu basit örnek uygulama iki düğme içerir. Biri aramayı yapmak için, diğeri ise aramayı kapatmak için. Aşağıdaki adımlar, bu düğmelerin uygulamaya nasıl ekleneceğini gösterir.
- Panelde
Solution Explorer
UWP veyaMainWindows.xaml
WinUI 3 için adlıMainPage.xaml
dosyaya çift tıklayın. - Merkezi panelde kullanıcı arabirimi önizlemesi altında XAML kodunu arayın.
- XAML kodunu aşağıdaki alıntıyla değiştirin:
<TextBox x:Name="CalleeTextBox" PlaceholderText="Who would you like to call?" />
<StackPanel>
<Button x:Name="CallButton" Content="Start/Join call" Click="CallButton_Click" />
<Button x:Name="HangupButton" Content="Hang up" Click="HangupButton_Click" />
</StackPanel>
Uygulamayı SDK API'lerini çağırma ile ayarlama
Çağrı SDK'sı API'leri iki farklı ad alanındadır. Aşağıdaki adımlar, Visual Studio'nun IntelliSense'inin kod geliştirmeye yardımcı olmasını sağlayan bu ad alanları hakkında C# derleyicisini bilgilendirmektedir.
- Panelde
Solution Explorer
, dosyanın sol tarafındaki UWP veyaMainWindows.xaml
WinUI 3 için adlıMainPage.xaml
oka tıklayın. - veya
MainWindows.xaml.cs
adlıMainPage.xaml.cs
dosyaya çift tıklayın. - Geçerli
using
deyimlerin en altına aşağıdaki komutları ekleyin.
using Azure.Communication.Calling.WindowsClient;
Açık veya MainWindows.xaml.cs
açık tutunMainPage.xaml.cs
. Sonraki adımlarda bu koda daha fazla kod eklenir.
Uygulama etkileşimlerine izin ver
Daha önce eklenen kullanıcı arabirimi düğmelerinin yerleştirilen CommunicationCall
üzerinde çalışması gerekir. Bu, bir CommunicationCall
veri üyesinin veya MainWindow
sınıfına MainPage
eklenmesi gerektiği anlamına gelir.
Ayrıca, zaman uyumsuz işlemin başarılı CallAgent
olması için veri CallAgent
üyesinin de aynı sınıfa eklenmesi gerekir.
veya MainWindow
sınıfına aşağıdaki veri üyelerini MainPage
ekleyin:
CallAgent callAgent;
CommunicationCall call;
Düğme işleyicileri oluşturma
Daha önce XAML koduna iki kullanıcı arabirimi düğmesi eklendi. Aşağıdaki kod, kullanıcı düğmeyi seçtiğinde yürütülecek işleyicileri ekler. Aşağıdaki kod, önceki bölümdeki veri üyelerinden sonra eklenmelidir.
private async void CallButton_Click(object sender, RoutedEventArgs e)
{
// Start call
}
private async void HangupButton_Click(object sender, RoutedEventArgs e)
{
// End the current call
}
Nesne modeli
Aşağıdaki sınıflar ve arabirimler Azure İletişim Hizmetleri UWP için istemci kitaplığını çağırmanın bazı önemli özelliklerini işler.
Veri Akışı Adı | Açıklama |
---|---|
CallClient |
CallClient , çağrı istemci kitaplığının ana giriş noktasıdır. |
CallAgent |
CallAgent çağrıları başlatmak ve katılmak için kullanılır. |
CommunicationCall |
CommunicationCall , yerleştirilen veya birleştirilen çağrıları yönetmek için kullanılır. |
CommunicationTokenCredential |
, CommunicationTokenCredential örneğini CallAgent başlatmak için belirteç kimlik bilgisi olarak kullanılır. |
CallAgentOptions |
, CallAgentOptions çağıranı tanımlamak için bilgileri içerir. |
HangupOptions |
Aramanın HangupOptions tüm katılımcılarına sonlandırılıp sonlandırılmadığını bildirir. |
Video şeması işleyicisini kaydetme
XAML'nin MediaElement veya MediaPlayerElement gibi bir UI bileşeni, uygulamanın yerel ve uzak video akışlarını işlemek için bir yapılandırma kaydetmesi gerekir.
etiketleri Package.appxmanifest
arasına aşağıdaki içeriği Package
ekleyin:
<Extensions>
<Extension Category="windows.activatableClass.inProcessServer">
<InProcessServer>
<Path>RtmMvrUap.dll</Path>
<ActivatableClass ActivatableClassId="VideoN.VideoSchemeHandler" ThreadingModel="both" />
</InProcessServer>
</Extension>
</Extensions>
CallAgent'ı başlatma
öğesinden CallClient
bir CallAgent
örnek oluşturmak için, başlatıldıktan sonra bir nesneyi zaman uyumsuz olarak döndüren yöntemi CallAgent
kullanmanız CallClient.CreateCallAgentAsync
gerekir.
oluşturmak CallAgent
için bir CallTokenCredential
nesne ve CallAgentOptions
bir nesne geçirmeniz gerekir. Hatalı biçimlendirilmiş bir belirteç geçirilirse atıldığını unutmayın CallTokenCredential
.
Aşağıdaki kod içine eklenmelidir ve yardımcı işlevi uygulama başlatmada çağrılmalıdır.
var callClient = new CallClient();
this.deviceManager = await callClient.GetDeviceManagerAsync();
var tokenCredential = new CallTokenCredential("<AUTHENTICATION_TOKEN>");
var callAgentOptions = new CallAgentOptions()
{
DisplayName = "<DISPLAY_NAME>"
};
this.callAgent = await callClient.CreateCallAgentAsync(tokenCredential, callAgentOptions);
this.callAgent.CallsUpdated += Agent_OnCallsUpdatedAsync;
this.callAgent.IncomingCallReceived += Agent_OnIncomingCallAsync;
<AUTHENTICATION_TOKEN>
değerini kaynağınız için geçerli bir kimlik bilgisi belirteci ile değiştirin. Kimlik bilgisi belirtecinin kaynaklanması gerekiyorsa kullanıcı erişim belirteci belgelerine bakın.
Video kamera ile 1:1 araması yerleştirme
oluşturmak CallAgent
için gereken nesneler artık hazır. Zaman uyumsuz olarak görüntülü arama oluşturma CallAgent
ve yerleştirme zamanı geldi.
private async void CallButton_Click(object sender, RoutedEventArgs e)
{
var callString = CalleeTextBox.Text.Trim();
if (!string.IsNullOrEmpty(callString))
{
if (callString.StartsWith("8:")) // 1:1 Azure Communication Services call
{
this.call = await StartAcsCallAsync(callString);
}
}
if (this.call != null)
{
this.call.RemoteParticipantsUpdated += OnRemoteParticipantsUpdatedAsync;
this.call.StateChanged += OnStateChangedAsync;
}
}
private async Task<CommunicationCall> StartAcsCallAsync(string acsCallee)
{
var options = await GetStartCallOptionsAsynnc();
var call = await this.callAgent.StartCallAsync( new [] { new UserCallIdentifier(acsCallee) }, options);
return call;
}
var micStream = new LocalOutgoingAudioStream(); // Create a default local audio stream
var cameraStream = new LocalOutgoingVideoStreamde(this.viceManager.Cameras.FirstOrDefault() as VideoDeviceDetails); // Create a default video stream
private async Task<StartCallOptions> GetStartCallOptionsAsynnc()
{
return new StartCallOptions() {
OutgoingAudioOptions = new OutgoingAudioOptions() { IsMuted = true, Stream = micStream },
OutgoingVideoOptions = new OutgoingVideoOptions() { Streams = new OutgoingVideoStream[] { cameraStream } }
};
}
Yerel kamera önizlemesi
İsteğe bağlı olarak yerel kamera önizlemesini ayarlayabiliriz. Video aracılığıyla işlenebilir MediaPlayerElement
:
<Grid>
<MediaPlayerElement x:Name="LocalVideo" AutoPlay="True" />
<MediaPlayerElement x:Name="RemoteVideo" AutoPlay="True" />
</Grid>
Yerel önizlemeyi MediaPlayerElement
başlatmak için:
private async void CameraList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (cameraStream != null)
{
await cameraStream?.StopPreviewAsync();
if (this.call != null)
{
await this.call?.StopVideoAsync(cameraStream);
}
}
var selectedCamerea = CameraList.SelectedItem as VideoDeviceDetails;
cameraStream = new LocalOutgoingVideoStream(selectedCamerea);
var localUri = await cameraStream.StartPreviewAsync();
LocalVideo.Source = MediaSource.CreateFromUri(localUri);
if (this.call != null) {
await this.call?.StartVideoAsync(cameraStream);
}
}
Uzak kamera akışını işleme
Olaya yanıt olarak çift işleyici ayarlayın OnCallsUpdated
:
private async void OnCallsUpdatedAsync(object sender, CallsUpdatedEventArgs args)
{
var removedParticipants = new List<RemoteParticipant>();
var addedParticipants = new List<RemoteParticipant>();
foreach(var call in args.RemovedCalls)
{
removedParticipants.AddRange(call.RemoteParticipants.ToList<RemoteParticipant>());
}
foreach (var call in args.AddedCalls)
{
addedParticipants.AddRange(call.RemoteParticipants.ToList<RemoteParticipant>());
}
await OnParticipantChangedAsync(removedParticipants, addedParticipants);
}
private async void OnRemoteParticipantsUpdatedAsync(object sender, ParticipantsUpdatedEventArgs args)
{
await OnParticipantChangedAsync(
args.RemovedParticipants.ToList<RemoteParticipant>(),
args.AddedParticipants.ToList<RemoteParticipant>());
}
private async Task OnParticipantChangedAsync(IEnumerable<RemoteParticipant> removedParticipants, IEnumerable<RemoteParticipant> addedParticipants)
{
foreach (var participant in removedParticipants)
{
foreach(var incomingVideoStream in participant.IncomingVideoStreams)
{
var remoteVideoStream = incomingVideoStream as RemoteIncomingVideoStream;
if (remoteVideoStream != null)
{
await remoteVideoStream.StopPreviewAsync();
}
}
participant.VideoStreamStateChanged -= OnVideoStreamStateChanged;
}
foreach (var participant in addedParticipants)
{
participant.VideoStreamStateChanged += OnVideoStreamStateChanged;
}
}
private void OnVideoStreamStateChanged(object sender, VideoStreamStateChangedEventArgs e)
{
CallVideoStream callVideoStream = e.CallVideoStream;
switch (callVideoStream.StreamDirection)
{
case StreamDirection.Outgoing:
OnOutgoingVideoStreamStateChanged(callVideoStream as OutgoingVideoStream);
break;
case StreamDirection.Incoming:
OnIncomingVideoStreamStateChanged(callVideoStream as IncomingVideoStream);
break;
}
}
uzak video akışını üzerinde MediaPlayerElement
işlemeye başlayın:
private async void OnIncomingVideoStreamStateChanged(IncomingVideoStream incomingVideoStream)
{
switch (incomingVideoStream.State)
{
case VideoStreamState.Available:
{
switch (incomingVideoStream.Kind)
{
case VideoStreamKind.RemoteIncoming:
var remoteVideoStream = incomingVideoStream as RemoteIncomingVideoStream;
var uri = await remoteVideoStream.StartPreviewAsync();
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
RemoteVideo.Source = MediaSource.CreateFromUri(uri);
});
/* Or WinUI 3
this.DispatcherQueue.TryEnqueue(() => {
RemoteVideo.Source = MediaSource.CreateFromUri(uri);
RemoteVideo.MediaPlayer.Play();
});
*/
break;
case VideoStreamKind.RawIncoming:
break;
}
break;
}
case VideoStreamState.Started:
break;
case VideoStreamState.Stopping:
break;
case VideoStreamState.Stopped:
if (incomingVideoStream.Kind == VideoStreamKind.RemoteIncoming)
{
var remoteVideoStream = incomingVideoStream as RemoteIncomingVideoStream;
await remoteVideoStream.StopPreviewAsync();
}
break;
case VideoStreamState.NotAvailable:
break;
}
}
Aramayı sonlandırma
Bir çağrı yerleştirildikten sonra, HangupAsync
çağrıyı CommunicationCall
kapatmak için nesnesinin yöntemi kullanılmalıdır.
Çağrısının HangupOptions
tüm katılımcılarına sonlandırılıp sonlandırılmaması gerektiğini bildirmek için bir örneği de kullanılmalıdır.
aşağıdaki kod içine HangupButton_Click
eklenmelidir.
var call = this.callAgent?.Calls?.FirstOrDefault();
if (call != null)
{
var call = this.callAgent?.Calls?.FirstOrDefault();
if (call != null)
{
foreach (var localVideoStream in call.OutgoingVideoStreams)
{
await call.StopVideoAsync(localVideoStream);
}
try
{
if (cameraStream != null)
{
await cameraStream.StopPreviewAsync();
}
await call.HangUpAsync(new HangUpOptions() { ForEveryone = false });
}
catch(Exception ex)
{
var errorCode = unchecked((int)(0x0000FFFFU & ex.HResult));
if (errorCode != 98) // Sample error code, sam_status_failed_to_hangup_for_everyone (98)
{
throw;
}
}
}
}
Kodu çalıştırma
Visual Studio'da uygulamasının , x86
veya ARM64
için derlediğinden emin olun, ardından uygulamayı çalıştırmaya başlamak için x64
hit tuşuna basınF5
. Bundan sonra, tanımlanan çağrıyı aramak için düğmeye tıklayın CommunicationCall
.
Uygulama ilk kez çalıştırıldığında sistemin kullanıcıdan mikrofona erişim izni vermesi istendiğini unutmayın.