Aracılığıyla paylaş


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

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ı CallAgentyaparak bir createCallAgent ö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.

Örnekteki getDeviceManager yöntemini kullanarak CallClient öğesine erişmek için deviceManager yöntemini kullanabilirsiniz.

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ı 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. Call Agent'ın iki olası durumu vardır.

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: Eğer bir belirtecin süresi dolmuşsa veya geçersizse Call Agent örnek bu hatayla bağlantıyı keser.
  • connectionIssue: İstemcinin Microsoft altyapısına bağlanmasıyla ilgili bir sorun varsa, birçok yeniden denemeden sonra Call AgentconnectionIssue hatasını ortaya çıkarır.

Call Agent yerel bilgisayarınızın Microsoft altyapısına bağlı olup olmadığını, connectionState özelliğinin geçerli değerini inceleyerek denetleyebilirsiniz. Etkin bir connectionStateChanged çağrı sırasında Call Agent bağlantı durumunun Bağlı'dan Bağlantısız duruma değişip değişmediğini 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, aramaya neyin Ses ve Görüntü ilettiğini kontrol etmenizi sağlar.

Aramada deviceManager ses ve video akışlarınızı iletebilen yerel cihazları listelemek için öğesini kullanın. Yerel cihazın mikrofonlarına ve kameralarına erişim izni istemek için de kullanabilirsiniz deviceManager .

deviceManager'a erişmek için callClient.getDeviceManager() yöntemini çağırabilirsiniz:

const deviceManager = await callClient.getDeviceManager();

Yerel cihazları alma

Yerel cihazlara erişmek için deviceManagergetCameras() numaralandırma yöntemlerini kullanabilirsiniz getMicrophones. 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 DeviceManagerhoparlö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 (UFD) tetiklenebilir ve tarayıcıya ve işletim sistemine bağlı olarak mikrofon çalışmayı durdurur.

Yerel video yayını

Kullanıcıların bir aramada video göndermesi için bir LocalVideoStream nesne oluşturmanız gerekir.

const localVideoStream = new LocalVideoStream(camera);

Parametre olarak geçirilen kamera yöntemi tarafından VideoDeviceInfo döndürülen bir deviceManager.getCameras() nesnedir.

A LocalVideoStream aşağıdaki özelliklere sahiptir:

  • source cihaz bilgileridir.

    const source = localVideoStream.source;
    
  • mediaStreamType, Videoveya ScreenSharingolabilirRawMedia.

    const type: MediaStreamType = localVideoStream.mediaStreamType;
    

Yerel kamera önizlemesi

yerel kameranızdan akış işlemeye başlamak için deviceManager ve VideoStreamRenderer kullanabilirsiniz.

LocalVideoStream 'i oluşturduktan sonra, VideoStreamRenderer'i ayarlamak için kullanın. VideoStreamRenderer öğesini oluşturduktan sonra, sayfanıza çocuk olarak ekleyebileceğiniz bir görünüm elde etmek için createView() yöntemini çağırın.

Bu akış diğer katılımcılara gönderilmez. Yerel bir önizleme beslemesidir.

// 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, VideoStreamRenderer'dan türetilen görünüm üzerinde "dispose" işlemini gerçekleştirin. VideoStreamRenderer atıldıktan sonra, önizlemenizi içeren DOM Düğümündeki removeChild() yöntemini çağırarak görünümü html ağacından 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, DeviceAccess ve audio izinlerinin verilip verilmediğini gösteren bir video nesneyle birlikte yöntem döner.

console.log(result.audio);
console.log(result.video);

Notlar

  • videoDevicesUpdated olayı, video cihazları takıldığında veya çıkarıldığında tetiklenir.
  • audioDevicesUpdated ses cihazları takılıyken olay tetiklenir.
  • 'yi ilk oluşturduğunuzda DeviceManager, izinlerin henüz verilmemesi durumunda herhangi bir cihaz hakkında bilgi vermez. Başlangıçta cihaz adı boş olur ve ayrıntılı cihaz bilgileri içermez. DeviceManager.askPermission()’yi aramanız gerekir, bu da kullanıcıdan cihaz erişimi ister. Kullanıcı erişime izin verdiğinde, cihaz yöneticisi sistemdeki cihazlar hakkında bilgi edinip cihaz listelerini güncelleştirir ve audioDevicesUpdated ve videoDevicesUpdated olaylarını gönderir. Kullanıcı sayfayı yeniler ve bir cihaz yöneticisi oluşturursa, kullanıcı daha önce erişim izni verdiği için cihaz yöneticisi cihazlar hakkında bilgi edinir. Başlangıçta cihaz listeleri doldurulmuş olur 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ü arama yapma

Önemli

Şu anda yalnızca bir giden yerel video akışı desteklenmektedir.

Görüntülü arama yapmak için getCameras() yöntemini kullanarak deviceManager içindeki yerel kameraları listelemeniz gerekir.

Bir kamera seçtikten sonra, bir LocalVideoStream örneği oluşturmak için onu kullanın. onu videoOptions dizisinde localVideoStream bir öğe olarak CallAgentstartCall yöntemine 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 CallAgent.join() API ile görüntülü bir aramaya katılabilir ve Call.Accept() API ile görüntülü bir aramayı kabul edebilir ve arama yapabilirsiniz.
  • 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 getCamerasdeviceManager yöntemini kullanarak kameraları listelemeniz gerekir. Ardından istenen kamerayla LocalVideoStream için yeni bir örnek oluşturun ve LocalVideoStream nesnesini mevcut bir çağrı nesnesinin startVideo yöntemine geçirin.

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, arama örneğindeki LocalVideoStream koleksiyonuna bir Video türünde localVideoStreams ö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 localVideoStream örneği, öğesinin stopVideo yöntemine Call geçirin.

await call.stopVideo(localVideoStream);

Etkin bir LocalVideoStream varken, o switchSource örneğindeki LocalVideoStream işlevini çağırarak farklı bir kamera cihazına 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 call.startVideo() kullanarak video başlatırsanız, bu yöntem bir SourceUnavailableError tetikler ve cameraStartFailed kullanıcıya yönelik tanılama true durumuna getirilir.
  • yöntemine yapılan bir çağrı, localVideoStream.switchSource() true olarak ayarlanmasına neden olur cameraStartFailed . 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 CallkullanabilirsinizisLocalVideoStarted:

// 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 startScreenSharing() zaman uyumsuz yöntemini Call kullanabilirsiniz:

Ekran paylaşımını başlatma

// Start screen sharing
await call.startScreenSharing();

Not

Ekran paylaşımı gönderme yalnızca masaüstü tarayıcıları için desteklenir.

LocalVideoStream koleksiyonunda ekran paylaşımını bulma

Ekran paylaşımını başarıyla göndermeye başladıktan sonra, arama örneğindeki LocalVideoStream koleksiyonuna bir ScreenSharing örneği türü localVideoStreams 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. Önizlemedeki özellikler genel kullanıma açıktır ve tüm yeni ve mevcut Microsoft müşterileri tarafından kullanılabilir.

Ö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 özellikler kısıtlanmış olabilir.

Daha fazla bilgi için, Microsoft Azure Önizlemeleri için Ek Kullanım Koşulları bölümüne bakın.

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 stopped 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ı görüntülemek için ilk adım, görüntülemek istediğiniz RemoteVideoStream üzerine bir referans almaktır.

Uzak katılımcıyı yalnızca videoStreams dizininden veya video akışından (RemoteParticipant) geçirerek işleyebilirsiniz. Uzak katılımcılar koleksiyonuna Call nesnesi aracılığıyla erişilir.

const remoteVideoStream = call.remoteParticipants[0].videoStreams[0];
const streamType = remoteVideoStream.mediaStreamType;

RemoteVideoStream işleyebilmek için isAvailableChanged olayına abone olmanız gerekir. isAvailable özelliği true olarak değişirse, uzak katılımcı bir video akışı gönderiyor. Bundan sonra, yeni bir örneği VideoStreamRendereroluşturun ve ardından zaman uyumsuz VideoStreamRendererView yöntemini kullanarak yeni createView 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, tüm VideoStreamRenderer'u veya belirli bir VideoStreamRendererView'i 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}`);
    });
}

Uzaktaki video akışı sırasında yükleme simgesini biçimlendirmek 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 özelliği, iki (2) veya daha fazla katılımcıdan oluşan bir grup çağrısında belirli bir anda farklı katılımcılardan gelen kaç videonun en uygun şekilde işlenebileceği konusunda uygulamaları bilgilendirmek için kullanın.

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. Belirli bir anda farklı katılımcı uygulamalarından kaç videonun görüntülenmesi gerektiğini optimalVideoCount değeri 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 on (10) saniye) vardır.

Kullanım

Bu optimalVideoCount özellik bir arama özelliğidir. OptimalVideoCount nesnesinin feature yöntemi aracılığıyla Call özelliğine başvurmanız gerekir.

Ardından optimalVideoCount değiştiğinde bildirim almak için on yöntemini OptimalVideoCountCallFeature kullanarak bir dinleyici ayarlayabilirsiniz. Değişikliklerin aboneliğinden çıkmak için off yöntemini çağırarak işlemi gerçekleştirebilirsiniz.

İşlenebilen en fazla gelen video sayısı 16'dır. 16 gelen videoyu düzgün bir şekilde desteklemek için, bilgisayarın en az 16 GB RAM'e ve üç (3) yaşından küçük dört (4) çekirdek veya daha büyük bir CPU'ya ihtiyacı vardır.

const optimalVideoCountFeature = call.feature(Features.OptimalVideoCount);
optimalVideoCountFeature.on('optimalVideoCountChanged', () => {
    const localOptimalVideoCountVariable = optimalVideoCountFeature.optimalVideoCount;
})

Örnek kullanım: Uygulamanız, grup çağrılarında En uygun Video Sayısı değişikliklerine abone olur. Optimal video sayısındaki bir değişiklik, ya yeni bir işleyici createView yöntemi oluşturarak ya da görünümleri dispose kaldırıp uygulama düzenini buna göre güncelleyerek ele alınır.

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: veya VideoolabilirScreenSharing.
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.

    • Aşağıdaki senaryolarda bayrak false'a taşınır.

      • Bir mobil tarayıcıda bulunan bir uzaktan katılımcı, tarayıcı uygulamasını arka plana alır.
      • 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.
    • Aşağıdaki senaryolarda bayrak true'a 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 katılımcı, video duraklatıldı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.

    • "isReceiving bayrağı false olduğunda, uzak video akışı üzerinde bir yükleme döndürücüsü görüntüleyebilirsiniz." Yükleme döndürücüsü uygulamanız gerekmez, ancak daha iyi bir kullanıcı deneyimi için en yaygın kullanılma şekli yükleme döndürücüsüdür.

    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 arayüzüne eklenebilecek VideoStreamRendererView örneği oluşturun. Asenkron createView() yöntemini kullanın; akış işlemeye hazır olduğunda çözülür ve DOM ağacında herhangi bir yere eklenebilecek olan öğeyi temsil eden bir target özelliğine sahip video bir nesne döndürür.

videoStreamRenderer.dispose();

videoStreamRenderer ve tüm ilişkili VideoStreamRendererView örneklerini kaldırın.

VideoStreamRendererView yöntemleri ve özellikleri

VideoStreamRendererView oluşturduğunuzda, scalingMode ve isMirrored özelliklerini belirtebilirsiniz. scalingMode, Stretchveya CropolabilirFit. Eğer isMirrored belirtilmişse, işlenen akış dikey olarak çevrilir.

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 scalingMode güncelleştirebilirsinizupdateScalingMode:

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. Önizlemedeki özellikler genel kullanıma açıktır ve tüm yeni ve mevcut Microsoft müşterileri tarafından kullanılabilir.

Ö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 özellikler kısıtlanmış olabilir.

Daha fazla bilgi için, Microsoft Azure Önizlemeleri için Ek Kullanım Koşulları bölümüne bakın.

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:

  • Video akışları gönderme işleminin 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 CallAgent 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 yalnızca bir kameraya uygulanabilir, her iki kameraya aynı anda uygulanamaz.

SDK’yı yükleyin

Proje düzeyindeki build.gradle dosyanızı bulun ve mavenCentral() dosyasını buildscript altındaki depolar listesine ekleyin allprojects:

buildscript {
    repositories {
    ...
        mavenCentral()
    ...
    }
}
allprojects {
    repositories {
    ...
        mavenCentral()
    ...
    }
}

Ardından modül düzeyi build.gradle dosyanızdaki dependencies bölümüne aşağıdaki satırları ekleyin:

dependencies {
    ...
    implementation 'com.azure.android:azure-communication-calling:1.0.0'
    ...
}

Gerekli nesneleri başlatma

CallAgent örneği oluşturmak için, bir createCallAgent örneğinde CallClient yöntemini çağırmanız gerekir. Bu çağrı zaman uyumsuz olarak bir CallAgent örnek nesnesi döndürür.

createCallAgent yöntemi, CommunicationUserCredential kapsülleyen bir bağımsız değişkeni argüman olarak alır.

DeviceManager öğesine erişmek için önce bir callAgent örneği oluşturmanız gerekir. Ardından CallClient.getDeviceManager yöntemini kullanarak DeviceManager alabilirsiniz.

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 kullanmak için cihazları yönetmeniz gerekir. Cihazları kullanmak, aramalar sırasında ses ve görüntüyü neyin ilettiğini kontrol etmenize olanak tanır.

nesnesi, DeviceManager ses/video akışlarınızı iletmek için bir çağrıda kullanılacak yerel cihazları listelemenizi sağlar. Ayrıca, yerel tarayıcı API'sini kullanarak bir kullanıcıdan mikrofon ve kameraya erişim izni istemenizi sağlar.

deviceManager öğesine erişmek için callClient.getDeviceManager() yöntemini çağırın.

Context appContext = this.getApplicationContext();
DeviceManager deviceManager = callClient.getDeviceManager(appContext).get();

Yerel cihazları listeleme

Yerel cihazlara erişmek için Cihaz Yöneticisi'nde numaralandırma yöntemlerini kullanın. 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 DeviceManager ve Renderer kullanabilirsiniz. Bu akış diğer katılımcılara gönderilmez. Yerel bir önizleme beslemesidir. Akışın işlenmesi 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ı yapma

Uyarı

Şu anda yalnızca bir giden yerel video akışı desteklenmektedir. Görüntülü arama yapmak için API'yi kullanarak deviceManagergetCameras yerel kameraları listelemeniz gerekir. Bir kamera seçtikten sonra, bir LocalVideoStream örneği oluşturmak için kullanın ve bunu, videoOptions dizisindeki bir öğe olarak localVideoStream'e bir call yöntemiyle geçirin. Arama bağlandıktan sonra, seçili kameradan diğer katılımcılara otomatik olarak bir video akışı göndermeye başlar.

Not

Gizlilikle ilgili endişelerden dolayı, video yerel olarak önizlenmediyse çağrıya paylaşılmıyor. Daha fazla bilgi 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 getCameraList işlemi kullanarak deviceManager 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 LocalVideoStream koleksiyona bir localVideoStreams ö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 LocalVideoStreamlocalVideoStreams bulunan örneği geçirin:

call.stopVideo(appContext, currentLocalVideoStream).get();

Video gönderilirken bir switchSource örneği üzerinde LocalVideoStream çağırarak farklı bir 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

Uzaktaki bir katılımcıyı RemoteVideoStream görüntülemek için bir OnVideoStreamsUpdated etkinliğine 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 gerçekleştiğinde, yeni bir Renderer örneği oluşturun, ardından zaman uyumsuz RendererView API'yi kullanarak yeni bir createView oluşturun ve uygulamanızın kullanıcı arabirimine, herhangi bir yere view.target ekleyin.

Bir uzak akışın kullanılabilirliği her değiştiğinde, tamamını Renderer yok etmeyi, belirli RendererView birini yok etmeyi veya bunları korumayı seçebilirsiniz, ancak bu, boş bir video karesinin görüntülenmesine yol açar.

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ışı aşağıdaki özelliklere sahiptir:

  • Id - Uzak video akışının kimliği.

    int id = remoteVideoStream.getId();
    
  • MediaStreamType- veya VideoolabilirScreenSharing.

    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

Renderer nesnesi aşağıdaki yöntemleri kullanır.

  • 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 VideoStreamRendererView öğesini at. Kullanıcı arabiriminden tüm ilişkili görünümleri kaldırdıktan sonra çağırın.

    VideoStreamRenderer.dispose()
    
  • Uzak video akışının boyutunu (genişlik/yükseklik) ayarlamak için kullanın StreamSize.

    StreamSize renderStreamSize = VideoStreamRenderer.getSize();
    int width = renderStreamSize.getWidth();
    int height = renderStreamSize.getHeight();
    

RendererView yöntemleri ve özellikleri

VideoStreamRendererView oluştururken, bu görünüm için geçerli olan ScalingMode ve mirrored özelliklerini belirtebilirsiniz.

Ölçeklendirme modu, CROP veya FIT'den biri olabilir.

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

Çeşitli bağımsız değişkenlerden updateScalingMode veya RendererView olanı kullanarak, ScalingMode.CROP nesnesinde ScalingMode.FIT işlemiyle ölçeklendirme modunu daha sonra güncelleyebilirsiniz.

// 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şturmayacaksınız. Testleri Dahil Et onay kutusunu temizleyebilirsiniz.

Xcode içinde proje oluşturma penceresini gösteren ekran görüntüsü.

CocoaPods kullanarak paketi ve bağımlılıkları yükleme

  1. 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
    
  2. pod install'i çalıştırın.

  3. Xcode kullanarak açın .xcworkspace .

Mikrofona erişim isteme

Cihazın mikrofonuna erişmek için, NSMicrophoneUsageDescription kullanarak uygulamanızın bilgi özellik listesini 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. Ü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. Dosyanın en üstüne import bildirimi ekleyerek AzureCommunicationCalling kitaplığını içeri aktarın. Buna ek olarak, ithal et.AVFoundation Koddaki ses izni istekleri için buna ihtiyacınız vardır.

import AzureCommunicationCalling
import AVFoundation

CallAgent'ı başlatma

Bir CallAgent öğesinden CallClient örnek oluşturmak için, başlatıldıktan sonra zaman uyumsuz şekilde bir callClient.createCallAgent nesnesi döndüren bir CallAgent yöntem kullanmanız 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 nesnesini oluşturduğunuz CallClient'e 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

Videoyu Arama ile kullanmaya başlamak için cihazları nasıl yöneteceğinizi bilmeniz gerekir. Cihazlar, aramaya neyin Ses ve Görüntü ilettiğini kontrol etmenizi sağlar.

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 de sağlar. deviceManager nesnesine callClient üzerinden erişebilirsiniz.

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ılar için değildir; 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 denetlemenizi sağlayan bir dizi özellik ve yöntem içerir.

// 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 arama yapma

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

Uzaktaki katılımcıların akışlarını listelemek için videoStreams koleksiyonlarını 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, "Blank App, Packaged (WinUI 3 in Desktop)" şablonunu kullanarak yeni bir proje oluşturun ve tek sayfalık bir WinUI 3 uygulaması ayarlayın. 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:

  1. Araçlar seçeneğine, ardından NuGet Paket Yöneticisi ve Çözüm için NuGet Paketlerini Yönet’e tıklayarak NuGet Paket Yöneticisi'ni açın.
  2. Gözat'ı seçin ve arama kutusuna Azure.Communication.Calling.WindowsClient yazın.
  3. Ön sürümü dahil et onay kutusunun seçili olduğundan emin olun.
  4. Azure.Communication.Calling.WindowsClient paketini ve ardından Azure.Communication.Calling.WindowsClient1.4.0-beta.1 veya daha yeni bir sürümü seçin.
  5. Sağ bölmedeki Azure İletişim Hizmetleri projeye karşılık gelen onay kutusunu seçin.
  6. Yükle'yi seçin.

Mikrofona erişim isteme

Uygulama kameraya erişmek istiyor. Evrensel Windows Platformu (UWP) uygulamalarında, uygulama bildirim dosyasında kamera özelliğini bildirmeniz gerekir.

  1. Projeyi Visual Studio'da açın.
  2. Çözüm Gezgini panelinde uzantılı .appxmanifest dosyaya çift tıklayın.
  3. Özellikler sekmesine tıklayın.
  4. Camera Yetenekler listesinden onay kutusunu seçin.

Çağrıyı başlatmak ve kapatmak için kullanıcı arabirimi düğmeleri oluşturun.

Bu örnek uygulama iki düğme içerir. Biri aramayı yapmak için, diğeri ise aramayı kapatmak için.

  1. Çözüm Gezgini panelinde UWP veya MainPage.xaml WinUI 3 için adlı MainWindows.xaml dosyaya çift tıklayın.
  2. Merkezi panelde kullanıcı arabirimi önizlemesi altında XAML kodunu arayın.
  3. Aşağıdaki alıntıyı kullanarak XAML kodunu 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.

Visual Studio'nun IntelliSense'in kod geliştirmeye yardımcı olmasını sağlayarak C# derleyicisini bu ad alanları hakkında bilgilendirmek için aşağıdaki adımları tamamlayın.

  1. Çözüm Gezgini panelinde, UWP için adlandırılmış olan dosyanın sol tarafındaki MainPage.xaml oka veya WinUI 3 için adlandırılmış dosyanın sol tarafındaki MainWindows.xaml oka tıklayın.
  2. veya MainPage.xaml.csadlı MainWindows.xaml.cs dosyaya çift tıklayın.
  3. Geçerli using deyimlerin en altına aşağıdaki komutları ekleyin.
using Azure.Communication.Calling.WindowsClient;

MainPage.xaml.cs veya MainWindows.xaml.cs açık tutun. Sonraki adım daha fazla kod ekler.

Uygulama etkileşimlerini etkinleştirme

Eklediğimiz kullanıcı arabirimi düğmelerinin yerleştirilen CommunicationCallüzerinde çalışması gerekir. CommunicationCall veri üyesini MainPage veya MainWindow sınıfına eklemeniz gerektiği anlamına gelir. Ayrıca, CallAgent oluşturma işleminin başarılı olması için zaman uyumsuz işlemi etkinleştirmeniz gerekir. Aynı sınıfa bir CallAgent veri üyesi ekleyin.

Aşağıdaki veri üyelerini MainPage veya MainWindow sınıfına ekleyin.

CallAgent callAgent;
CommunicationCall call;

Düğme işleyicileri oluşturma

Daha önce XAML koduna iki kullanıcı arabirimi düğmesi eklemiştik. Aşağıdaki kod, kullanıcı düğmeyi seçtiğinde çalıştırılacak işleyicileri ekler.

Önceki bölümde yer alan veri üyelerinin arkasına aşağıdaki kodu ekleyin.

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.

İsim 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, CallAgent örneğini başlatmak için belirteç kimlik bilgisi olarak kullanılır.
CallAgentOptions , CallAgentOptions çağıranı tanımlamak için bilgileri içerir.
HangupOptions HangupOptions aramanın sonlandırılıp sonlandırılmayacağını tüm katılımcılara bildirir.

Video şeması işleyicisini kaydetme

XAML MediaElement veya MediaPlayerElementgibi bir UI bileşeni, uygulamanın yerel ve uzak video akışlarını işlemek için bir yapılandırma kaydetmesini gerektirir.

Aşağıdaki içeriği Package etiketleri Package.appxmanifest arasına ekleyin:

<Extensions>
    <Extension Category="windows.activatableClass.inProcessServer">
        <InProcessServer>
            <Path>RtmMvrUap.dll</Path>
            <ActivatableClass ActivatableClassId="VideoN.VideoSchemeHandler" ThreadingModel="both" />
        </InProcessServer>
    </Extension>
</Extensions>

CallAgent'ı başlatma

Bir CallAgent örneği oluşturmak için CallClient'den, başlatıldıktan sonra bir CallClient.CreateCallAgentAsync nesnesini eşzamansız olarak döndüren fonksiyonu CallAgent kullanmalısınız.

CallAgent oluşturmak için bir CallTokenCredential nesnesi ve bir CallAgentOptions nesnesi geçirmeniz gerekir. Hatalı biçimlendirilmiş bir belirteç geçirildiğinde CallTokenCredential atıldığını unutmayın.

Başlatma sırasında çalışması için aşağıdaki kodu yardımcı işlevin içine ekleyin.

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 belirtecini kaynak oluşturma hakkında daha fazla bilgi için bkz. kullanıcı erişim belirteci.

Video kamera ile 1:1 araması yapma

CallAgent oluşturmak için gereken nesneler artık hazır. Ardından CallAgent zaman uyumsuz olarak oluşturun ve bir görüntülü arama başlatın.

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 GetStartCallOptionsAsync();
    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 LocalOutgoingVideoStream(this.viceManager.Cameras.FirstOrDefault() as VideoDeviceDetails); // Create a default video stream

private async Task<StartCallOptions> GetStartCallOptionsAsync()
{
    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. Videoyu MediaPlayerElement aracılığıyla işleyebilirsiniz.

<Grid>
    <MediaPlayerElement x:Name="LocalVideo" AutoPlay="True" />
    <MediaPlayerElement x:Name="RemoteVideo" AutoPlay="True" />
</Grid>

Yerel önizlemeyi MediaPlayerElementbaş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 selectedCamera = CameraList.SelectedItem as VideoDeviceDetails;
    cameraStream = new LocalOutgoingVideoStream(selectedCamera);

    var localUri = await cameraStream.StartPreviewAsync();
    LocalVideo.Source = MediaSource.CreateFromUri(localUri);

    if (this.call != null) {
        await this.call?.StartVideoAsync(cameraStream);
    }
}

Uzak kamera akışını görüntü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;
    }
}

Uzaktan video akışını MediaPlayerElement üzerinde oluşturmaya 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ı yapıldıktan sonra, çağrıyı kapatmak için HangupAsync nesnesinin CommunicationCall yöntemini kullanın.

Çağrının HangupOptions sonlandırılması gerekip gerekmediğini katılımcılara bildirmek için örneğini kullanın.

içine aşağıdaki kodu HangupButton_Clickekleyin.

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

  1. Visual Studio'nun uygulamayı x64, x86 veya ARM64 için derlediğinden emin olun.
  2. Uygulamayı çalıştırmaya başlamak için F5 tuşuna basın.
  3. Tanımlanan alıcıya çağrı yapmak için CommunicationCall düğmesine tıklayın.

Uygulama ilk kez çalıştırıldığında sistem, kullanıcıdan mikrofona erişim izni vermesini ister.

Sonraki adımlar