Захват видео с камеры и передача его по сети

в 7:37, , рубрики: .net, aforge.net, MJPEG, метки: , , ,

Предисловие

Не так давно, возникла необходимость захвата видео с web камеры и передавать его по сети используя .Net.
Так как с подобной задачей я столкнулся впервые, то первым делом начал искать информацию по этому вопросу.
Как выяснилось, что в чистом .Net нет поддержки работы с web камерами. Перебрав несколько различных библиотек, свой выбор остановил на Aforge.net.

Aforge.net — это фреймворк для решения целого ряда задач, из которого нам понадобится библиотеки AForge.Video.

Захват изображения

Для захвата видео с устройства видео ввода существует класс AForge.Video.DirectShow.VideoCaptureDevice. Ему необходимо задать моникер устройства с которого будет происходить захват. Так же необходимо задать обработчик события NewFrame. Это событие возникает каждый раз, когда с устройства будет получен новый кадр, который и передается в обработчик в виде объекта Bitmap, где его уже можно обработать:

private void VideoSourceNewFrame(object sender, AForge.Video.NewFrameEventArgs eventArgs)
{
    var img = (Image) eventArgs.Frame;
    using (var ms=new MemoryStream())
    {
        img.Save(ms,ImageFormat.Jpeg);
       //Сохраняем изображение в массив байт, для последующего формирования mjpeg
        _bufImage = ms.ToArray();
    }
}


Запуск видеозахвата осуществляется вызовом метода Start().

Список доступных видеокамер, установленных в системе, можно получить с помощью класса FilterInfoCollection, передав ему, в качестве параметра, необходимую категорию устройств:

var videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);

Это класс представляет из себя коллекцию элементов FilterInfo, которые содержат в себе два поля:

  • Name — название устройства
  • MonikerString — моникер устройства.

Таким образом, получив моникер устройства мы можем передать его в класс VideoCaptureDevice.

Формирование видео-потока MJPEG

MJPEG (Motion JPEG) является простейшим алгоритмом видеосжатия, поэтому свой выбор я остановил именно на нем.
Поток видео MJPEG представляет из себя последовательно идущие кадры в JPEG формате дополненные http заголовком:

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Transfer-Encoding: chunked
Content-Type: multipart/x-mixed-replace; boundary=--myboundary
Expires: -1
--myboundary
Content-Type: image/jpeg
Content-Length:96719
.....image.......
--myboundary
Content-Type: image/jpeg
Content-Length:96720
.....next image.......

Пример реализации:

public ActionResult Video()
{
    Response.Clear();
    //Устанавливает тип передаваемых данных и разделитель кадров
    Response.ContentType = "multipart/x-mixed-replace; boundary=--myboundary";
    //Отключаем кеширование
    Response.Expires = 0;
    Response.Cache.SetCacheability(HttpCacheability.NoCache);

    var ae = new ASCIIEncoding();
    //Передаем поток пока клиент не отключится
    while (Response.IsClientConnected)
    {
        try
        {
            //_bufImage - переменная, в которой хранится новый кадр в формате jpeg
            var buf = _bufImage;
            //Формируем заголовок разделителя
            var boundary = ae.GetBytes("rn--myboundaryrnContent-Type: image/jpegrnContent-Length:"
                                        + buf.Length + "rnrn");
            Response.OutputStream.Write(boundary, 0, boundary.Length);
            Response.OutputStream.Write(buf, 0, buf.Length);
            Response.Flush();
            //Усыпляем поток, для поддержки частоты кадров 20 кадров/с
            Thread.Sleep(50);

        }
        catch (Exception)
        {

        }

    }
    Response.End();



    return null;
}

Aforge.net
MJPEG
Ссылка на исходник

Автор: vassav

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js