15 min read

Plex 미디어 서버의 "직접 재생"

Plex 를 쓰는 이유

최근에 OTT 들이 파편화되고, 구독 가격이 점점 올라가고, 그나마 있던 작품도 계약 문제로 사라지는 문제들이 있어서, 예전 방식으로 돌아가는 분들이 많다.

굳이 세계 멸망을 염두에 두는 프레퍼족이 아니더라도, 나만의 컬렉션을 소장하고 싶어하는 사람들은 여전히 수요가 있기에 셀프 호스팅 스트리밍 서버를 운영하시는 분들이 많은데, Plex, Emby, Jellyfin 등이 있으며, 그 중에서도 Plex 가 유명하다.

Plex 는 하드웨어 트랜스코딩 기능과 풍부한 미디어 메타데이터 정리 기능, 무엇보다도 다양한 클라이언트 생태계를 지원한다. 당신이 아는 거의 모든 플랫폼에 Plex 앱은 반드시 있다. 그러니, 다양한 플랫폼에서 사용할 예정이라면 거의 선택의 여지가 없다.

가끔 할인 행사를 통해 Lifetime 가격이 $100~ 초반에 구매할수 있었으나, 최근 $250 로 급격하게 가격이 올라버렸다. 블랙프라이데이나 Plex week 로 불리는 할인 행사에 구매하는 것 외에는, 너무 비싼 가격이 되버렸다. (아무래도 최근 OTT 의 가격 인상과 파편화로 다시 Plex 에 유입이 많아져서 그런것으로 생각된다.)

실시간 트랜스코딩과 직접 재생

Plex 는 서버 와 클라이언트로 나뉘며, 서버측에는 미디어 파일들을 올려두고, 클라이언트(웹, 폰, 태블릿, 스마트TV)를 통해 서버의 내용을 꺼내서 볼수 있다.

이때, "직접 재생" 과 "실시간 트랜스코딩" 이라는 두가지 형태로 재생된다.

직접 재생은 미디어를 모바일 기기에서 직접 실시간 디코딩하여 재생하는 것을 말하고, 실시간 트랜스코딩은 클라이언트가 처리할 수 있는 코덱으로 서버가 실시간으로 미디어를 변환해주는 동작이다.

단적으로 말하면, "직접 재생" 의 장점이 압도적으로 많기 때문에 아주 어쩔수 없는 상황이 아니라면 "실시간 트랜스코딩" 형태로 재생되는 것은 단점이 많다.

"실시간 트랜스코딩" 이 빛을 발하는 두가지 케이스가 있는데, 하나는 모바일 기기가 구형이라 미디어를 직접 재생할수 없는 경우와, 네트워크 대역폭을 절약하기 위해 화질을 낮춰 재생하는 경우, 실시간 트랜스코딩을 사용하는 이유가 된다.

한국의 높은 네트워크 속도와, 고화질 기기로 미디어 감상을 선호하는 평균적인 상황에서는 실시간 트랜스코딩은 화질이 손상되며 높은 비트레이트 설정으로 인해 오히려 원본보다 대역폭 요구가 높아지는 문제가 발생한다.

트랜스코딩은 과거 모바일 기기의 발전이 더뎠을 때, 모바일 기기에서 직접 미디어를 재생할수 없었다. 정확히 말하자면, 재생할수 있는 미디어가 매우 제한되었다. 이유는 모바일 기기의 AP(CPU) 에서 하드웨어적으로 디코딩할수 있도록 코덱이 지원되어야 하는데, 스트리밍이 유행하기 전에는 그러한 지원이 부족했다.

그런 이유로, 서버의 미디어를 모바일 기기에서 재생하기 위해서는, 모바일 기기가 재생할 수 있는 종류의 코덱을 사용하여 서버에서 실시간으로 "다시" 인코딩하여 모바일기기에 전송했어야 했다. 이렇게 다시 인코딩하는 과정을 "트랜스코딩" 이라고 한다. 이 방식으로 유명한 애플의 AirPlay 나, 인터넷 방송 플랫폼, 아주 과거의 PMP 에 넣기 위한 동영상 인코딩 등이 있었다.

요즘 시대는 넷플릭스나 유튜브가 대중화되면서 대부분의 핸드폰에 내장된 AP 에서 다양한 미디어 코덱이 하드웨어 디코딩이 지원되어 별도의 변환 없이도 실시간 재생이 가능해졌으니, 예전처럼 모바일이 처리할 수 있도록 서버가 변환해주는 실시간 트랜스코딩이 필요하지는 않게 되었다.

또한, 어렵게 고화질로 구축해놓은 라이브러리가 직접 재생이 아니라, 실시간 트랜스코딩으로 동작하게 되면 화질도 떨어지고, 대역폭 소모도 높아진다.

이미 고화질의 미디어는 릴리즈 그룹들이 정성을 다해 최신의 코덱으로 최소의 손실을 유지하며 압축한 형태인데, 실시간 트랜스코딩 동작에서는 그 최적화를 풀어헤치고 모바일이 처리할수 있는 코덱으로 재인코딩을 하게 되니, 화질은 떨어지면서 소모하는 대역폭은 더 높아지는 현상이 나타난다.

실시간 트랜스코딩은 소프트웨어 트랜스코딩과 하드웨어 트랜스코딩으로 나뉘는데, 소프트웨어 트랜스코딩은 CPU 를 100% 잡아먹는 무시무시한 자원 소모를 보인다. 소프트웨어 트랜스코딩이 동작하면, 높은 사용 부하로 인해 다른 기능들이 버벅이거나 동작하지 않을 수 있다. 그나마 Nvidia 계열 GPU 나, 최신의 Intel 계열 CPU 를 사용하는 경우 HW 트랜스코딩을 지원할 수 있는데, 그러면 CPU 부하가 거의 사라진다.

즉, 이 Plex 서버를 나 혼자 사용하는게 아니라 가족이나 친구들고 함께 사용한다면 자원 사용을 최소화 하기 위해 "직접 재생" 상태를 유지하여야 하고, 최소한 어쩔수 없다면 하드웨어(HW) 트랜스코딩 상태를 유지해야 한다. 한사람이라도 소프트웨어(SW) 트랜스코딩으로 사용한다면, 높은 CPU 사용율 때문에 Plex 서버가 뻗어버린다.

그러니, Plex 를 사용한다면 어떻게든 "직접 재생" 상태를 유지해야 한다. "실시간 트랜스코딩" 형태로 동작하게 된다면 뭔가 잘못된 것이다. 그러나 요구조건이 많다.

직접 재생의 조건

직접 재생을 위해서는 다음과 같은 조건이 필요하다.

  1. Plex 클라이언트가, 서버의 네트워크에 직접 접근할 수 있거나(동일 네트워크), 혹은 그렇게 할 수 있도록 대안적인 방법(포트 노출, 혹은 리버스 프록시)이 설정되어있는 경우
  2. 클라이언트의 AP 에서 미디어 코덱을 하드웨어 디코딩을 지원하는 경우
  3. 자막이 있을 경우, SRT (Subrip) 을 사용하는 경우
  4. 상기 모든 조건이 만족하면 "직접 재생" 으로 미디어가 재생된다.
  5. 그렇지 않으면 "실시간 트랜스코딩" 으로 미디어가 재생된다.

가장 이상적인 환경은, 동일한 네트워크에 있는 Plex 서버와 최소한 2020년 이후에 구매한 스마트폰이나 스마트TV 정도라면 문제없이 상기의 조건을 만족시킬 수 있다.

현재 재생 상태를 확인하는 방법

안드로이드 스마트TV 의 경우, 재생화면 하단에 설정에서 "Nerd 통계(Statistics)" 라는 항목이 있는데, 디버깅에 준하는 재생 정보가 표시된다. 여기에 "직접 재생" 혹은 "실시간 트랜스코딩" 에 대한 정보가 출력되며, 만약 직접재생 상태가 아니라면 그 이유가 뭔지도 출력된다.

그 외에는 Plex 서버에서 관리자 권한으로 들어가면 대시보드에 현재 재생 큐들이 보이며 직접 재생인지 실시간 트랜스코딩인지에 대한 정보가 출력된다.

자막은 반드시 SRT 으로 할 것

한국사람 한정으로 문제가 자막인데, 과거에는 거의 모든 자막이 SMI (SAMI) 로만 배포되어 어려움이 있었고, 지금도 라이브러리를 구축하시는 분들은 어쩔수 없이 SMI 로 수집하시는 분들이 있다.

Plex 는 SMI 자막을 만나면 영상에 입히는(Burn) 작업을 하므로 직접 재생 조건에 모두 맞더라도, 실시간 트랜스코딩으로 동작하게 된다. 그러므로 SMI 자막은 반드시 SRT 로 변환하는게 좋다.

다행히 SMI 를 SRT 로 변환하는 온라인 도구는 많으나, 가끔 싱크가 어긋나는 문제들이 있어서 어려움은 여전히 있다.

네트워크

Plex 를 직접 운영하시는 분들은 대개 홈랩을 취미로 하시는 분들이 많아서 이 부분에서 큰 어려움은 없겠으나, 미디어 라이브러리를 수집하시는 취미 활동가라면 다소 어려움을 느낄 수 있는 부분이 네트워크다.

Plex 서버와 클라이언트가 같은 네트워크 안에 있다면 아무 문제가 없다. 그러나 Plex 서버가 클라이언트와 전혀 다른곳에 있어서, 네트워크가 다르다면 여러 설정이 필요하다.

가장 기본적이고 예전부터 쓰던 방법으로는, Plex 에서 요구하는 32400/tcp 포트를 외부로 노출하는 방법이 있다. 집에 공유기를 사용하시는 분이라면, "포트 포워딩" 이나, UPNP 라는 방법으로 이것을 이룰 수 있다. 인터넷에서 가장 많이 찾을 수 있는 방법이다.

다음으로는, plex.direct 라는 방법이 있다. Plex 에서 모든 유료 사용자에게 제공하는 기능인데, HTTPS 를 지원하기 위한 자체적인 도메인과 인증서를 함께 제공한다. 홈랩을 취미로 하는 사람이 아니고서야, 도메인을 구입했다거나 인증서를 발급하는 방법을 알기는 어려우므로, 가능하면 Plex 에서 제공하는 이 방식을 따르는 것이 좋다. 공유기를 통해 노출한 32400 포트를 그대로 사용하므로, 대부분의 사용자들은 이 방식이 최선이다.

마지막으로, 홈랩에 충분히 지식이 있을 경우 자기가 직접 도메인을 구입하고 인증서를 발급받아 별도의 도메인을 연결해 reverse-proxy 에 연동해서 사용하는 방법이 있다. 사실 이 단어만 보면 어떻게 해야할지 바로 떠오르는 분들은 그대로 하시면 된다.

상기 세가지 방법 중 하나로, 자신의 Plex 서버에 접속한 후, 네트워크 설정에서 다음을 활성화 하면 된다.

  •  WAN IP를 LAN 대역폭으로 사용

만약 plex.direct 나, 자신이 직접 별도의 도메인을 구성해 plex 서버에 접근하는 경우라면, "사용자 서버 접속 URL" 항목에 다음중 하나의 형태로 도메인을 입력해야 한다.

  • https://*.<임의의해쉬값>.plex.direct:32400 # plex 서버가 32400 포트로 노출된 경우
  • https://<도메인>:443 # reverse-proxy 를 통해 서비스 하는 경우

보통 https:// 로 시작하면 포트를 별도로 입력하지 않는게 관례지만, 다양한 클라이언트들이 이 정보를 이용하기 때문에 명시적으로 포트를 입력해야 한다고 한다.

단순하게 32400 포트만 노출해서 사용하려는 경우, Plex 서버의 "원격 액세스" 기능을 활성화해서 외부로부터 32400 포트를 통해 Plex 서버로 접속되는지 확인할수 있다.

만약 plex.direct 나 도메인을 사용해서 서비스 하는 경우라면, "원격 액세스" 를 비활성화해도 된다.

보통 여기까지 한 후, https://plex.tv 에 접속해서 로그인하면, 본인의 plex 서버에 접근할 수 있다.

가능한 문제들

Plex 서버는 기본적으로는 웹서버이다. 다만 32400 이라는 비정규 포트를 사용할 뿐이다. 다양한 클라이언트를 지원하기 위해 암호화 되지 않는 http:// 도 지원하지만, 기본적으로는 암호화된 https:// 을 사용해야 한다. 그래야 정상적으로 장치들이 연결된다.

만약 Plex 서버가 전문 방화벽 장비 뒤에 있는 경우, 가끔 통신이 차단되는 경우가 있다. Plex 서버가 클라이언트에게 미디어를 빠르게 전송하는 과정의 패턴을 방화벽이 일시 차단하는 경우가 있다. 가정용 공유기 등에서는 일어나지 않는 일이고, 기업용 방화벽에서 일어날 수 있는 일이다. Plex 서버를 기업용 방화벽(특히 IDS, IPS) 뒤에서 운영하는 경우라면 다양한 변수가 있을 수 있다. 만약 이 문제에 해당한다면, HTTPS 로 암호화 되어있더라도 트래픽의 패턴을 보고 감지할 수 있으므로, 외부의 방화벽이 없는 네트워크를 통해 plex 서버로 진입하게 할 수 있다.

다른 가능한 문제로는, (이것도 역시 전문 방화벽의 경우 해당) plex.direct 도메인을 사용할 경우 DNS rebinding 로 인해 접근이 불허되는 경우가 있다. 홈랩 사용자인 경우 OPNsense 혹은 pfsense 를 사용하는 경우가 그렇다. 이때는 DNS rebinding 를 해제하면 된다. (참조: https://calvin.me/plex-with-dns-over-tls/) 개인 도메인으로 직접 IP 를 연결해서 사용하는 경우는 이러한 불일치가 일어나지 않으므로 해당하지 않는다.

또한, 32400 을 노출하는 경우, Plex 서버의 네트워크 설정에서 "인증없이 허용되는 네트워크 및 IP 주소 목록" 에 전체 네트워크를 절대로 포함해서는 안된다. 32400 포트를 통해 접속하는 사용자가 만약 "인증없이 허용되는 네트워크 및 IP 주소 목록" 에 포함되는 경우, 별도의 인증없이 곧바로 모든 라이브러리에 접근할 수 있게 된다. 예를 들어, "0.0.0.0/0" 네트워크는 말 그대로 "모든" 네트워크를 말하는데, 이 문장이 포함되게 되면 전세계 사람들에게 무료로 라이브러리를 제공하는 공짜 스트리밍 서비스가 되는 셈이다.

그러니, 가장 간단한 방법은, 집에서 가정용 공유기를 통해 포트포워딩으로 32400 을 노출하되, "인증없이 허용되는 네트워크 및 IP 주소 목록" 에 포함되지 않도록 사용하는것이 변수가 가장 적을 것이다.

사실 홈랩 사용자들은 알아서 대부분의 문제를 잘 해결할 것이니...