© 2020, Developed by Hieu Dev

Tìm hiểu về WebRTC trong .NET 6 MVC

Như các bạn đã biết, WebRTC (Web Real-Time Communication) là một open-source miễn phí, cho phép các ứng dụng web và các trang web nắm bắt và tùy chọn phát trực tiếp audio và video, cũng như trao đổi dữ liệu tùy ý giữa các trình duyệt mà không yêu cầu trung gian.

Tìm hiểu về WebRTC trong .NET 6 MVC

Các công nghệ đằng sau WebRTC được triển khai như một tiêu chuẩn web mở và có sẵn dưới dạng các API JavaScript thông thường trong tất cả các trình duyệt chính.

Cài đặt WebRTC trong .NET 6 MVC

Ở trong bài viết này, mình sẽ sử dụng .NET 6, là phiên bản .net mới nhất hiện tại để tích hợp webRTC vào project, nhưng ở phiên bản trước và sau, chúng ta cũng dùng tương tự và không ảnh hưởng nhiều đến phiên bản.

Bước 1: Khởi tạo project với ASP.NET Core Web App (Model-View_Controller)

Tìm hiểu về WebRTC trong .NET 6 MVC

Bước 2: Bây giờ ta cần VideoController.cs.

    public class VideoController : Controller
    {
        [HttpGet]
        public IActionResult Index()
        {
            return View();
        }
    }

Như code bên trên, đơn giản ta chỉ cần method Index để tạo ra view để chưa code tích hợp webRTC của chúng ta.

Bước 3: Tạo view cho phương thức Index():

@{
    ViewData["Title"] = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<div id="container">
      <div class="video-item">
          <video id="gum" playsinline autoplay muted poster="https://s1.uphinh.org/2021/07/21/loading.gif"></video>
          <div class="btn-group">
              <button id="start" class="hbtn btn btn-success"><i class="fa fa-video-camera" aria-hidden="true"></i></button>
            <button id="stop" class="hbtn btn btn-danger" style="display: none;"><i class="fa fa-video-camera" aria-hidden="true"></i></button>
          </div>
      </div>
      <div><span id="errorMsg"></span></div>
      <select id="codecPreferences" disabled style="display:none"></select>
      <input type="checkbox" id="echoCancellation" style="display:none">
</div>

Như code bên trên, các bạn có thể thấy, ta dùng thẻ video để chiết xuất hình ảnh từ webcam của chúng ta, và bên dưới ta gọi đến các button action cho việc mở và tắt camera.

Bước 4: Và bước này rất quan trọng, vì ta dùng code javascript gọi đến open source WebRTC và định nghĩa ra các method để chiết xuất đến camera của chúng ta.

Cụ thể bạn sẽ tạo file Video.js trong wwwroot/js/Video.js, và thêm toàn bộ code sau:

'use strict';

/* globals MediaRecorder */

let mediaRecorder;
let recordedBlobs;

const codecPreferences = document.querySelector('#codecPreferences');

const errorMsgElement = document.querySelector('span#errorMsg');

function handleSuccess(stream) {
    console.log('getUserMedia() got stream:', stream);
    window.stream = stream;

    const gumVideo = document.querySelector('video#gum');
    gumVideo.srcObject = stream;

    getSupportedMimeTypes().forEach(mimeType => {
        const option = document.createElement('option');
        option.value = mimeType;
        option.innerText = option.value;
        codecPreferences.appendChild(option);
    });
    codecPreferences.disabled = false;
}


async function init(constraints) {
    try {
        const stream = await navigator.mediaDevices.getUserMedia(constraints);
        handleSuccess(stream);
    } catch (e) {
        console.error('navigator.getUserMedia error:', e);
        errorMsgElement.innerHTML = `navigator.getUserMedia error:${e.toString()}`;
    }
}

document.querySelector('button#start').addEventListener('click', async () => {
    document.querySelector('button#start').disabled = true;
    document.querySelector('button#start').style.display = 'none';
    document.querySelector('button#stop').style.display = 'block';
    document.querySelector('button#stop').disabled = false;
    const hasEchoCancellation = document.querySelector('#echoCancellation').checked;
    const constraints = {
        audio: {
            echoCancellation: { exact: hasEchoCancellation }
        },
        video: {
            width: 1280, height: 720
        }
    };
    console.log('Using media constraints:', constraints);
    await init(constraints);
});

document.querySelector('button#stop').addEventListener('click', async () => {
    document.querySelector('button#stop').disabled = true;
    document.querySelector('button#start').disabled = false;
    document.querySelector('button#start').style.display = 'block';
    document.querySelector('button#stop').style.display = 'none';
    const video = document.querySelector('video#gum');
    const mediaStream = video.srcObject;
    await mediaStream.getTracks().forEach(track => track.stop());
    video.srcObject = null;
});


function getSupportedMimeTypes() {
    const possibleTypes = [
        'video/webm;codecs=vp9,opus',
        'video/webm;codecs=vp8,opus',
        'video/webm;codecs=h264,opus',
        'video/mp4;codecs=h264,aac',
    ];
    return possibleTypes.filter(mimeType => {
        return MediaRecorder.isTypeSupported(mimeType);
    });
}



Bước 5: Bây giờ ta cần thêm css cho đẹp các button và video bằng cách tạo ra file css như đường dẫn wwwroot/css/Video.css với code sau:

p.borderBelow {
    margin: 0 0 20px 0;
    padding: 0 0 20px 0;
}

video {
    vertical-align: top;
    --width: 25vw;
    width: var(--width);
    height: calc(var(--width) * 0.5625);
}

    video:last-of-type {
        margin: 0 0 20px 0;
    }

    video#gumVideo {
        margin: 0 20px 20px 0;
    }

#gum {
    width: 100% !important;
    height: 70vh !important;
    border: none !important;
}
.hbtn {
    border-radius: 50% !important;
    width: 40px;
    height: 40px;
}

video#gum {
    border: 1px solid #eee !important;
    border-radius: 10px;
}


Bước 6: Cuối cùng ta cần thêm những path sau vào bên trong _Layout.cshtml:

<link rel="stylesheet" href="~/css/Video.css" />
<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
<script src="~/js/Video.js" asp-append-version="true" async></script>


Cụ thể các vị trí đặt trong file _Layout.cshtml như sau:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - CaptureVideo.WebApp</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
    <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
    <link rel="stylesheet" href="~/CaptureVideo.WebApp.styles.css" asp-append-version="true" />
    <link rel="stylesheet" href="~/css/Video.css" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css" integrity="sha512-5A8nwdMOWrSz20fDsjczgUidUBR8liPYU+WymTZP1lmY9G6Oc7HlZv156XqnsgNUzTyMefFTcsFH/tnJE/+xBg==" crossorigin="anonymous" referrerpolicy="no-referrer" />
    
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container-fluid">
                <a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">CaptureVideo.WebApp</a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2022 - CaptureVideo.WebApp - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
        </div>
    </footer>
    <script src="~/lib/jquery/dist/jquery.min.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>
    <script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
    <script src="~/js/Video.js" asp-append-version="true" async></script>
    @await RenderSectionAsync("Scripts", required: false)
</body>
</html>


Sau khi hoàn thành các bước trên, bạn đã có thể chiết xuất đến video của bạn với 2 action đơn giản là bật, tắt camera.

Tìm hiểu về WebRTC trong .NET 6 MVC

Lời kết

Như ta thấy, WebRTC có thể được sử dụng cho nhiều mục đích khác nhau, từ việc truyền tải video, audio cho đến gửi dữ liệu theo thời gian thực giữa hai hoặc nhiều thiết bị với nhau mà không nhất thiết phải đi qua server trung gian. 

Điều này giúp giảm độ trễ trong việc truyền tải, giảm độ phức tạp khi phát triển ứng dụng cũng như giảm chi phí vận hành (vì không phải trả tiền thuê server, tiền điện, tiền bảo dưỡng...), kéo theo đó giá bán dịch vụ nếu có thì cũng sẽ thấp hơn.

Mong bài viết hữu ích, chúc các bạn thành công!
Hieu Ho.

Đăng nhận xét

Mới hơn Cũ hơn

TOGETHER

WE GROW