[기술 소개] 딥러닝 스트리밍 서버 (1)

스트리밍 서버에 딥러닝을 적용해 보자!

Daeyang Cho
KLleon
8 min readMay 11, 2022

--

들어가며

코로나19는 사람과 사람 간 거리를 두도록 했지만, 발전하는 기술은 사람들이 거리감을 느끼지 않고 소통할 수 있도록 했습니다. 우리는 줌으로 회사 미팅에 참석하고, 페이스톡으로 멀리 떨어진 부모님과 안부를 물으며, 인스타 라이브로 좋아하는 셀럽들과 소통하는 세상에 살고 있습니다.

오늘은 이러한 동영상 스트리밍에 딥러닝을 적용하는 기술을 소개하려 합니다.

점점 온라인 미팅이 자연스러워지고 있다.

스트리밍 서버를 만들 때 대표적으로 두 가지 프레임워크 중에 하나를 선택해서 만드는 경우가 많습니다.

하나는 ffmpeg이고, 다른 하나는 gstreamer입니다. 두 가지 프레임워크 모두 다양한 코덱과 필터를 제공합니다. 그러나 여기에 딥러닝을 적용하려면, 따로 딥러닝 모델을 돌릴 수 있는 커스텀 필터를 제작해야 합니다.

이러한 수고로움을 덜어주고자 탄생한 gstreamer의 딥러닝 플러그인들이 있습니다. 하나는 NVIDIA에서 제공하는 DeepStream이고, 다른 하나는 삼성 리서치에서 만든 NNStreamer입니다.

오늘은 라이센스가 더 자유로운 NNStreamer를 설명하고, 예제까지 적용해 보도록 하겠습니다.

NNStreamer란

NNStreamer는 스트리밍 서버 개발자가 딥러닝 모델을 스트림 파이프라인과 필터에 쉽고 효율적으로 적용하도록 도와주는 gstreamer 플러그인 세트입니다.

NNStreamer는 다음과 같은 목표를 갖고 있습니다.

  • gstreamer 스트림에 딥러닝 프레임워크 연결(e.g., pytorch, tensorflow)을 제공합니다.
  • 사실상 표준 미디어 스트림 프레임워크인 gstreamer를 사용하여 딥러닝 모델로 미디어 스트림을 구성하는 쉬운 방법을 제공합니다.

NNStreamer는 메인 repository와, NNStreamer를 활용한 예제들이 있는 repository도 있습니다. 예제 repository에는 tensorflow와 tensorflow lite를 활용한 C++ 예제와 tensorflow lite를 활용한 Python 예제 등이 있습니다.

오늘은 PyTorch로 짜여진 딥러닝 모델을 NNStreamer에 얹어보고자 합니다. PyTorch 모델을 돌리기 위해서는 3가지 순서가 필요합니다.

  1. PyTorch 모델의 input/output shape을 NNStreamer tensor_filter의 input/output shape과 맞춰야 합니다.
  2. PyTorch 모델을 TorchScript로 바꿔야 합니다.
  3. NNStreamer에서 TorchScript 모델을 돌리기 위해, NNStreamer와 libtorch (PyTorch의 C++ API)를 연결해야 합니다.

Input/ouput shape

딥러닝 모델을 돌리기 위해 사용하는 NNStreamer의 필터는 tensor_filter입니다. tensor_filter는 BHWC (Batch, Height, Width, Channel)의 모양으로 인풋을 받습니다. 아웃풋 또한 BHWC로 내보냅니다. 그렇기 때문에 동일한 모양으로 맞춰서 PyTorch 모델을 구현해야 합니다.

TorchScript

TorchScript는 PyTorch 코드에서 직렬화 및 최적화 가능한 모델을 생성하는 방법입니다. 이를 통해 C++과 같은 고성능 환경에서 최적화된 PyTorch 모델을 사용할 수 있습니다. NNStreamer에서 딥러닝 모델을 돌리는 필터가 C++로 구현되어 있으며, 이 필터는 TorchScript를 파라미터로 받습니다. 그렇기 때문에 우리는 PyTorch 모델을 TorchScript로 바꾸어야 합니다.

NNStreamer build

마지막으로 NNStreamer에서 TorchScript를 돌릴 수 있도록 NNSteramer와 libtorch를 연결해 주어야 합니다. PPA를 통해 다운 받는 NNStreamer는 libtorch와의 연동이 자동으로 이뤄지지 않기 때문에, NNStreamer 소스 코드를 받아서 새로 빌드 해야 합니다. NNStreamer의 소스 코드와 libtorch를 각각 다운 받고, repository에 있는 이 링크를 따라 빌드를 진행할 수 있습니다.

이때, pkg-config가 libtorch를 인식할 수 있도록 pc 파일을 작성해 주어야 합니다. 라이브러리들의 경로는 자신의 머신에 따라 알맞게 변경해 주시면 됩니다.

prefix=/usr/local/lib/libtorch
exec_prefix=${prefix}
includedir=${prefix}/include
libdir=${exec_prefix}/lib
cudaroot=/usr/local/cuda-11.1/
cudalibdir=${cudaroot}/targets/x86_64-linux/lib
cudalibstubs=${cudalibdir}/stubs
Name: pytorch
Description: pytorch static library 1.8.2+cu111
Version: 1.8.2
Requires: nvrtc-11.1 nvToolsExt-11.1 cudart-11.1 cufft-11.1 curand-11.1 cublas-11.1
Libs: -L${libdir} -lc10 -lc10_cuda -ltorch -ltorch_cpu -ltorch_cuda -ltorch_cuda_cu -ltorch_cuda_cpp -lgomp -lcudart -lnvToolsExt -L${cudalibstubs} -lcuda -L{cudalibdir} -lcudnn
Cflags: -I${includedir}

또한, build를 하실 때, NNStreamer repository의 root directory에 있는 meson.build 파일에서 필요한 option들을 설정하여야 합니다. NNStreamer의 meson.build는 기본적으로 warning을 error로 처리하는 옵션인 werror가 true로 설정되어 있습니다. 만약 warning들로 인해서 build가 안 되는 경우라면, default_options의 werror를 false로 바꿔주시고 build하면 되겠습니다.

이렇게 NNStreamer와 libtorch를 연결해 주었다면, 웹캠을 통해 들어온 미디어 스트림에 TorchScript를 적용할 수 있게 됩니다.

NNStreamer 데모

먼저, gstreamer와 nnsteamer, 그리고 웹캡의 설치가 잘 되었는지를 다음의 커맨드로 확인할 수 있습니다.

gst-launch-1.0 v4l2src name=cam_src ! videoconvert ! videoscale ! video/x-raw,format=RGB,width=640,height=480,framerate=30/1 ! tensor_converter ! tensor_decoder mode=direct_video ! videoconvert ! autovideosink

다음으로는, NNStreamer의 tensor_filter를 사용하여 TorchScript 모델을 돌려볼 수 있습니다. 이때 주의할 점은 tensor_filter에서 input과 output의 shape이 코드 내부에서 뒤집히기 때문에, input과 output을 CWHB (BHWC를 뒤집은 순서)로 넣어주어야 합니다. 저는 AnimeGANv2의 paprika 버전을 TorchScript로 바꾸어서 사용하였습니다.

gst-launch-1.0 v4l2src name=cam_src ! videoconvert ! videoscale ! video/x-raw,format=RGB,width=640,height=480,framerate=30/1 ! tensor_converter ! tensor_filter framework=pytorch model=pytorch_animae_ganv2_paprika_gpu.pt input=3:640:480:1 inputtype=uint8 output=3:640:480:1 outputtype=uint8 accelerator=true:gpu ! tensor_decoder mode=direct_video ! videoconvert ! autovideosink sync=false

NNStreamer 와 AnimeGANv2

마치며

이렇게 NNStreamer를 활용하여 PyTorch 딥러닝 모델을 스트리밍 서버에 적용하여 보았습니다. 이렇게 다양한 분야에서 사용되는 걸 보니, 딥러닝이 우리의 일상에 한 걸음 더 가까워진 것 같습니다.

클레온에서는 딥러닝 스트리밍 기술을 더욱 고도화하여 사람과 사람의 사이가 더욱 가까워지는 세상을 만들고자 합니다. 앞으로의 클레온의 행보에도 많은 기대 부탁드립니다!

--

--