iOS Safari와 호환되지 않는 VP9 비디오 업로드를 자동 감지하거나 거부

최근 자체 호스팅 Discourse 포럼에서 여러 동영상이 iPhone과 iPad에서 조용히 재생되지 않는 문제를 발견했습니다. 조사 결과, 원인은 동영상이 MP4 컨테이너 안에 VP9 코덱으로 인코딩되어 있었기 때문이었습니다. iOS Safari는 이 조합을 재생할 수 없습니다.

발생 과정

Facebook(그리고 아마도 다른 플랫폼들도)은 사용자가 콘텐츠를 다운로드할 때 VP9 인코딩된 동영상을 전달할 수 있습니다. 이러한 파일이 Discourse에 업로드되면 아무 문제 없이 허용됩니다. .mp4 확장자만으로는 내부 코덱에 대한 정보가 제공되지 않기 때문입니다. 데스크톱 브라우저와 Android에서는 동영상이 정상적으로 재생되므로 문제가 드러나지 않습니다. 반면 iOS Safari에서는 썸네일과 재생 버튼은 표시되지만, 탭하면 회전하는 로더만 나타납니다. 사용자는 이를 네트워크 문제로 오해하고 보고하지 않은 채 넘어가는 경우가 많습니다.

포착하기 어려운 이유

  • 파일 확장자(.mp4)가 정상 작동하는 H.264 파일과 동일합니다.
  • 데스크톱 브라우저는 VP9을 지원하므로 데스크톱에서 테스트하는 관리자는 문제를 발견하지 못합니다.
  • iOS 사용자는 개별 미디어 재생 실패를 보고하지 않는 경우가 많으며, 특히 같은 게시글의 다른 콘텐츠가 표시되고 재생되는 상황에서는 더욱 그러합니다.
  • 관리자용 경고나 오류 메시지가 없습니다.

권장 해결책

동영상 업로드 시 Discourse가 동영상 코덱을 검사할 수 있습니다(ffprobe는 이미 Docker 컨테이너에 포함되어 있습니다). 그리고 다음과 같은 조치를 취할 수 있습니다:

  1. 거부: VP9은 iOS에서 지원되지 않음을 설명하는 명확한 메시지와 함께 업로드를 거부하고, H.264로 재인코딩하도록 사용자에게 요청하거나,
  2. 자동 변환: 업로드 시 동영상을 H.264로 자동 변환합니다(일부 플랫폼이 업로드를 정규화하는 방식과 유사합니다).

옵션 1은 복잡성이 낮으며 이미 상당한 개선이 될 것입니다. 옵션 2는 원활한 사용자 경험을 위해 이상적입니다.

환경

  • 자체 호스팅 Discourse (Docker), 로컬 저장소 (S3 미사용)
  • Discourse 버전: 2026.4.0-latest
  • Discourse nginx 앞에 Apache 리버스 프록시 구성

임시 해결책

이 문제를 겪는 관리자를 위한 수정 방법은 다음과 같습니다:

  1. ffprobe를 사용하여 VP9 파일 식별
  2. ffmpeg -c:v libx264 -profile:v main -level 3.1 -r 30 -movflags +faststart 명령을 사용하여 H.264로 재인코딩
  3. uploads 테이블의 sha1, url, filesize 업데이트
  4. 영향받은 게시글 원본 마크다운의 upload:// 짧은 URL 토큰 업데이트
  5. 영향받은 게시글 다시 베이킹(Rebake)

대부분의 포럼 관리자가 수행할 수 없는 상당히 복잡한 수동 과정입니다.

1개의 좋아요

자동 변환에 대해 Discourse Video Stream :movie_camera:를 확인해 보세요.

로컬 자동 변환은 작동하지만, 대부분의 환경에서 안전하게 전달하는 것이 주요 문제입니다.

3개의 좋아요

Video Stream 플러그인에 대한 조언을 주셔서 감사합니다, @Falco. 제 것처럼 소규모의 취미 기반 포럼에서는 유료 제3자 서비스에 대한 의존성을 추가하는 것이 문제의 규모에 비해 과한 조치처럼 느껴집니다 — 물론, 대량 트래픽과 높은 비디오 사용률을 가진 사이트라면 그 매력을 이해할 수 있습니다.

로컬 트랜스코딩에 대한 말씀이 흥미롭습니다. 수정 과정에서 VPS에서 영향받은 9개 파일에 대해 수동으로 ffmpeg를 실행해 봤고, 서버는 아무 문제 없이 이를 처리했습니다. 업로드 시 동기 방식으로 이를 수행할 경우의 우려, 즉 CPU 스파이크, 타임아웃, 디스크 부하 등은 모두 현실적인 위험임을 이해합니다. 하지만 비동기 백그라운드 작업 방식을 사용하면 이러한 우려 대부분을 해결할 수 있지 않을까요? 업로드는 정상적으로 완료되고, 트랜스코딩은 이후 큐에 쌓인 작업으로 처리됩니다 — 이는 Discourse가 이미 이미지 섬네일 생성에 사용하고 있는 방식과 유사합니다. 이 경우 작업이 완료될 때까지 iOS에서는 비디오를 재생할 수 없게 되지만, 이는 허용 가능한 타협이라고 생각합니다.

완전한 트랜스코딩이 아니더라도, 더 가벼운 옵션 — 업로드 시 VP9 코덱을 감지하여 명확한 오류 메시지와 함께 거부하거나 관리자 패널에 표시하는 것 — 은 침묵하는 iOS 재생 실패를 진단할 기술적 배경이 없는 셀프호스팅 관리자에게 큰 도움이 될 것입니다.

1개의 좋아요

비디오는 사용자가 CPU를 과부하 시키기 위해 악의적으로 업로드할 수 있는 방법이 너무 많아 조금 더 복잡합니다. 특히 1vCPU 셀프호스팅 인스턴스의 경우 더욱 그렇습니다.

관리자가 트레이드오프를 수용할 수 있을 때만 선택할 수 있는 옵션이 되도록 여기서 플러그인을 구현해 볼 수 있습니다.

4개의 좋아요