HTML5 Canvas로 눈길 끄는 광고 만들기
📄

HTML5 Canvas로 눈길 끄는 광고 만들기

Created
Dec 27, 2022 09:33 AM
Tags
web
javascript
webgl
Conference
LINE DevDay 2021
Video preview

Introduce

  • LINE의 Creative Lab 개발 관련된 세션
    • Creative Lab : 자신이 만든 콘텐츠를 다른 LINE 서비스에 광고로 게시할 수 있는 서비스
  • HTML5 canvas 를 이용해 간단히 광고를 만들 수 있도록 구성
    • 앱은 영상을 만드는 프런트엔드와 영상 렌더링을 담당하는 Node.js 인코딩 서버로 구성됨
    • 빠른 렌더링을 위해 클라이언트에서는 WebGL 기반 GPU 하드웨어 가속을 이용
    • 서버에서는 headless-gl(OpenGL) 기반 GPU 하드웨어 가속을 이용
  • 이를 어떻게 기획하고 개발하고 배포했는지에 대해 소개 (여기서는 개발 관련된 내용만 적었습니다.)

Canvas에 요소 렌더링하기

폰트 렌더링하기

  • 폰트는 사이즈가 크다
    • 이를 각기 가져오는 것 : 네트워크를 통해 수 백 MB 사이즈를 전달받아야 하기에 비효율
  • 연구조사 결과
    • 폰트 렌더링 서버 구축
    • 폰트 서브셋 구성
  • 폰트 서버
      1. 클라이언트가 폰트 타입과 텍스트를 보내면
      1. 서버에서 클라이언트로 해당 폰트의 ‘이미지'를 보내는 방식
      1. 전체 폰트 파일을 다운로드 받는 시간에 비해 렌더링 된 이미지를 다운로드 받는 시간이 더 빠름
      1. 다만 텍스트를 자주 변경하게 된다면 많은 트래픽이 유발됨
  • 폰트 서브셋
      1. 폰트를 서브셋 형태로 만들어 제공
      1. 서브셋을 나누는 것 뿐만 아니라 unicode-range 를 추가로 이용
          • 브라우저에서 알아서 font-face 를 타깃해 가져올 수 있게 됨
      1. 브라우저는 사용자가 입력한 것에 기반해 필요한 폰트 서브셋을 알아서 불러옴
          • 전체 파일을 다운로드받을 필요가 없다
      1. 다만 이 방법은 모든 폰트의 원본 파일을 split 해줘야 함

도형 렌더링하기

  • SVG를 이용해 렌더링하기에 크기를 조절해도 해상도 이슈는 없다
  • Outline의 경우 Canvas의 Path2D를 이용해 그림

비디오 렌더링하기

  • 클라이언트에서 비디오를 보여주기 위해 GPU 하드웨어 가속을 이용
  • 다만 유의해야 할 몇 가지 사항이 존재
    • 그리기 시작하기 전 항상 모든 리소스를 GPU에 업로드해야 함
    • 모든 리소스는 이미지 형태여야 함
  • 처음 고려했던 비디오 인코딩 방법 → 프런트엔드에서 인코딩하기
    • Canvas에 CaptureStream 을 이용(MediaRecorder API)
    • 다만 사용자에게 영향을 미치는 몇 가지 단점이 있어 실제 사용은 하지 않음
      • 실제로는 인코딩이 아닌 녹화였기에, 인코딩에는 최소 영상 길이 이상의 시간이 소요됨 (가령 30초 영상이면, 인코딩에 최소 30초 이상 소요)
      • 사용자가 다른 브라우저로 전환하면 프로세스가 연기됨
      • 브라우저를 닫으면 프로세스가 취소됨 → 모두 사용자를 기다리게 하는 요소
  • 클라이언트에서 영상 만드는 것은 어찌되었든 불가능
    • FFmpeg을 이용해 백엔드에서 처리하자
  • 하드웨어 인코더
    • 서버에서 GPU를 추가해 속도를 높임
    • GPU에는 하드웨어 인코더가 있음 (CPP를 이용해 이걸 low-level sdk를 만들어 사용)
    • 인코딩 서버는 Node.js를 이용하기에 CPP와 Binding하는 방식을 이용

챌린지

Encoding Speed

  • 비교적 초기에 겪었던 문제
  • MediaRecorder 를 이용해 클라이언트에서 제작은 불가 → 서버에서 인코딩
    • 모두 프런트 개발자였기에 Node.js를 이용
    • 그러나 네이티브로 Canvas와 WebGL을 지원하지 않음 → node-canvas 그리고 headless-gl 이용
    • 이를 이용해 동일한 코드베이스로 클라이언트와 서버 둘 다 적용
  • 초기 렌더링 서버 구성도 (FFmpeg)
    • notion image
    • 이렇게 구성한 결과 프로세스가 느리고
    • GPU에서 램이나 SSD로 옮겨야 했기에 병목이 존재
  • 이후 서버 구성도 (HardWare Encoder + low-level SDK)
    • notion image
    • 이 방식을 이용하면 위의 Bottleneck이 완전히 제거됨
  • 성능 개선
    • 기존 : 30 sec (MediaRecorder)
    • 1차 개선 : 7 sec (Node.js + FFmpeg)
    • 2차 개선 : 2 sec (Node.js + low-level SDK + HW Encoder)

Support new effects

  • 현재는 비디오 효과를 위해 GLSL 이용
  • gl-transition 라이브러리를 이용하기에 여기에서 제공하는 효과만 사용이 가능
  • 향후 직접 GLSL을 이용한 비디오 효과를 구현해 더 많은 효과 제공 예정