개발

[C#, WPF, WebRTC] 비디오 채팅 애플리케이션을 구현하기 예제

딱딱키보드 2023. 5. 26. 15:26
728x90
SMALL

WPF로 WebRTC 예제를 만들기 위해서는 OpenTok API, PubNub API, WebRTC UWP NuGet 패키지를 사용하는 방법과 WebRTC.Net NuGet 패키지를 사용하는 방법이 있습니다. 이번에는 WebRTC.Net NuGet 패키지를 사용하는 방법으로 예제를 만들어보겠습니다.

먼저, Visual Studio에서 새 WPF 프로젝트를 만들어줍니다.

그 다음, NuGet 패키지 관리자에서 WebRTC.Net NuGet 패키지를 설치해줍니다. 설치가 완료되면, MainPage.xaml 파일에 다음과 같이 코드를 작성해줍니다.

MainPage.xaml:

<Window x:Class="WebRTCExample.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="WebRTC Example" Height="450" Width="800">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*"/>
            <ColumnDefinition Width="1*"/>
        </Grid.ColumnDefinitions>
        <Image x:Name="LocalVideoImage" Grid.Column="0" Stretch="UniformToFill" Margin="10" />
        <Image x:Name="RemoteVideoImage" Grid.Column="1" Stretch="UniformToFill" Margin="10" />
        <Button x:Name="StartButton" Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="0,0,0,10" Width="100" Height="30" Content="Start" Click="StartButton_Click"/>
        <Button x:Name="StopButton" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="0,0,0,10" Width="100" Height="30" Content="Stop" Click="StopButton_Click" IsEnabled="False"/>
    </Grid>
</Window>

 

다음으로, MainPage.xaml.cs 파일에 다음과 같이 코드를 작성해줍니다.

MainPage.xaml.cs:

using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Threading;
using Microsoft.Win32;
using Org.WebRtc;

namespace WebRTCExample
{
    public partial class MainPage : Window
    {
        private MediaStream _localStream;
        private MediaStreamTrack _localVideoTrack;
        private MediaStreamTrack _remoteVideoTrack;
        private PeerConnection _peerConnection;

        public MainPage()
        {
            InitializeComponent();
        }

        private void StartButton_Click(object sender, RoutedEventArgs e)
        {
            // Initialize WebRTC library
            WebRTC.Initialize(Windows.UI.Core.CoreDispatcherPriority.Normal);

            try
            {
                // Get local video stream
                var videoCaptureDevices = MediaDevice.GetVideoCaptureDevices();
                var selectedVideoCaptureDevice = videoCaptureDevices[new Random().Next(videoCaptureDevices.Count)];
                var settings = new MediaCaptureInitializationSettings { VideoDeviceId = selectedVideoCaptureDevice.Id };
                var mediaCapture = new MediaCapture();
                mediaCapture.InitializeAsync(settings).GetResults();
                _localVideoTrack = new VideoTrackSource(mediaCapture).CreateTrack();

                // Show local video
                _localStream = new MediaStream();
                _localStream.AddTrack(_localVideoTrack);
                var localVideoBrush = new VideoBrush();
                localVideoBrush.SetSource(_localVideoTrack.I420A.ToBitmap());
                           LocalVideoImage.Dispatcher.Invoke(() =>
            {
                LocalVideoImage.Stretch = Stretch.UniformToFill;
                LocalVideoImage.Source = localVideoBrush;
            }, DispatcherPriority.Normal);

            // Create peer connection
            _peerConnection = new PeerConnection();
            _peerConnection.OnIceCandidate += PeerConnection_OnIceCandidate;
            _peerConnection.OnTrack += PeerConnection_OnTrack;

            // Add local video stream to peer connection
            _peerConnection.AddStream(_localStream);

            // Create offer
            var offer = _peerConnection.CreateOffer();
            _peerConnection.SetLocalDescription(offer);

            // Send offer to remote peer
            // ...
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }

        StartButton.IsEnabled = false;
        StopButton.IsEnabled = true;
    }

    private void StopButton_Click(object sender, RoutedEventArgs e)
    {
        // Close peer connection
        _peerConnection.Close();

        // Stop local video
        _localVideoTrack.Dispose();
        _localStream.Dispose();
        LocalVideoImage.Source = null;

        // Stop remote video
        _remoteVideoTrack.Dispose();
        RemoteVideoImage.Source = null;

        StartButton.IsEnabled = true;
        StopButton.IsEnabled = false;
    }

    private void PeerConnection_OnIceCandidate(IceCandidate iceCandidate)
    {
        // Send ICE candidate to remote peer
        // ...
    }

    private void PeerConnection_OnTrack(MediaStreamTrackEvent trackEvent)
    {
        // Show remote video
        var remoteVideoBrush = new VideoBrush();
        remoteVideoBrush.SetSource(trackEvent.Track.I420A.ToBitmap());
        RemoteVideoImage.Dispatcher.Invoke(() =>
        {
            RemoteVideoImage.Stretch = Stretch.UniformToFill;
            RemoteVideoImage.Source = remoteVideoBrush;
        }, DispatcherPriority.Normal);

        _remoteVideoTrack = trackEvent.Track;
    }
}

 

이제 프로젝트를 빌드하고 실행하면, 로컬 비디오 스트림이 표시되고 'Start' 버튼을 누르면 WebRTC 연결이 생성됩니다. 연결이 생성되면, 생성된 offer를 원격 피어에게 전송해야 합니다. offer를 전송하는 방법은 OpenTok API, PubNub API 등을 사용하면 됩니다. offer를 수신한 원격 피어는 answer를 생성하여 다시 보내주면, 이를 수신한 로컬 피어는 SetRemoteDescription() 메서드를 사용하여 answer를 설정하면 원격 비디오 스트림이 표시됩니다.

이제 원격 비디오 스트림을 표시하기 위해 PeerConnection_OnTrack() 메서드가 호출됩니다. 이 메서드는 MediaStreamTrackEvent 객체를 매개변수로 받습니다. 이 객체에서는 원격 비디오 트랙을 가져올 수 있습니다. 가져온 트랙은 ToBitmap() 메서드를 사용하여 비디오 스트림을 비트맵 이미지로 변환할 수 있습니다. 변환된 비트맵 이미지는 VideoBrush 객체에 설정하여 RemoteVideoImage 컨트롤에 표시됩니다.

PeerConnection_OnIceCandidate() 메서드는 IceCandidate 객체를 매개변수로 받습니다. 이 객체에서는 ICE candidate 정보를 가져올 수 있습니다. 이 정보를 상대방에게 전송하여 WebRTC 연결을 완성합니다.

StopButton_Click() 메서드는 WebRTC 연결을 종료하고 로컬/원격 비디오 스트림을 중지합니다.

이제 WPF로 WebRTC 예제를 만드는 방법을 알아보았습니다. 이 예제를 기반으로 WebRTC를 사용하여 영상 통화, 화면 공유 등 다양한 기능을 구현할 수 있습니다.

728x90
LIST