Hdhomerun Tvheadend Jellyfin 연동
HDHomeRun + TVHeadend + Jellyfin 설정 가이드
이 문서는 Synology DS3617xs NAS 환경에서 HDHomeRun FLEX QUATRO(HDFX-4US) + TVHeadend + Jellyfin을 이용한 라이브 TV 시스템의 설명서 겸 매뉴얼입니다. 실제 운영 중인 서버 설정을 기반으로 작성되었습니다.

목차
1. 시스템 개요
1.1 전체 아키텍처
┌─────────────┐ 동축케이블 ┌──────────────────┐ LAN (UDP) ┌───────────────┐
│ D-Live │ ──────────────→ │ HDHomeRun │ ──────────────→ │ TVHeadend │
│ 케이블 벽체 │ RF 신호 │ FLEX QUATRO │ MPEG-TS │ (Docker) │
│ │ │ 192.168.1.51 │ │ 192.168.1.99 │
└─────────────┘ │ 4 ATSC-T 튜너 │ │ :9981 / :9982│
└──────────────────┘ └───────┬───────┘
│
HTSP (port 9982)
│
┌───────▼───────┐
┌──────────│ Jellyfin │──────────┐
│ │ (Docker) │ │
│ │ 192.168.1.99 │ │
│ │ :8096 │ │
│ └───────────────┘ │
│ │
┌────▼────┐ ┌────────┐ ┌────────┐ ┌────▼────┐
│ 웹브라우저│ │ iOS앱 │ │Android │ │ TV앱 │
│ (LAN) │ │ (외부) │ │ (외부) │ │ (LAN) │
└─────────┘ └────────┘ └────────┘ └─────────┘
1.2 데이터 흐름
케이블 RF 신호 → HDHomeRun (하드웨어 튜너, RF → MPEG-TS 변환)
→ TVHeadend (채널 매핑, EPG 관리, HTSP 스트리밍 서버)
→ Jellyfin (트랜스코딩, 사용자 인증, 웹/앱 재생)
→ 클라이언트 (브라우저, 모바일 앱, TV 앱)
1.3 구성 요약
| 구분 | 장비/소프트웨어 | 역할 | 접근 주소 |
|---|---|---|---|
| 케이블 제공자 | D-Live (딜라이브) | RF 신호 송출 | - |
| TV 튜너 | HDHomeRun FLEX QUATRO (HDFX-4US) | RF → 네트워크 스트림 변환 | http://192.168.1.51 |
| TV 서버 | TVHeadend 4.3 (Docker) | 채널/EPG 관리, 스트리밍 | http://192.168.1.99:9981 |
| 미디어 서버 | Jellyfin 10.10.6 (Docker) | 트랜스코딩, 재생, 사용자 관리 | http://192.168.1.99:8096 |
| NAS | Synology DS3617xs | Docker 호스트 | 192.168.1.99 |
1.4 서버 하드웨어 사양
| 항목 | 사양 |
|---|---|
| NAS 모델 | Synology DS3617xs |
| CPU | Intel Xeon D-1527 (4코어/8스레드, 2.2GHz) |
| RAM | 48GB |
| iGPU | 없음 (하드웨어 트랜스코딩 불가) |
| OS | DSM (Linux 기반) |
| Docker 경로 | /volume2/storage/docker/ |
2. HDHomeRun FLEX QUATRO (HDFX-4US)
2.1 역할
HDHomeRun은 TV 튜너 하드웨어입니다.
- 케이블(동축) 연결로 RF 신호를 수신
- RF 신호를 MPEG-TS 네트워크 스트림으로 변환
- 네트워크(LAN)를 통해 TVHeadend로 스트림 전달
- 동시 4채널 수신 가능 (4개 독립 튜너)
- 자체적으로 채널 관리나 EPG 기능은 없음 (단순 튜너 역할)
2.2 하드웨어 사양
| 항목 | 사양 |
|---|---|
| 모델 | HDFX-4US (HDHomeRun FLEX QUATRO) |
| 튜너 수 | 4개 (동시 4채널 시청/녹화 가능) |
| 지원 방식 | ATSC, Clear QAM |
| 네트워크 | 10/100/1000 Ethernet |
| 전원 | DC 5V (어댑터 포함) |
2.3 설정 영역
| 설정 항목 | 설정 위치 | 설명 |
|---|---|---|
| IP 주소 | HDHomeRun 웹 UI 또는 DHCP | 네트워크 주소 할당 |
| 튜너 모드 | TVHeadend에서 설정 | ATSC-T / Cable 등 |
| 펌웨어 업데이트 | HDHomeRun 웹 UI | 최신 펌웨어 유지 |
2.4 초기 설정 방법
Step 1: 물리적 연결
- 케이블 벽체 단자 → 동축케이블 → HDHomeRun CABLE IN 포트
- LAN 케이블 → HDHomeRun ETHERNET 포트 → 공유기/스위치
- 전원 어댑터 연결
Step 2: IP 확인
- HDHomeRun은 DHCP로 자동 IP 할당
- 공유기 관리 페이지에서 HDHomeRun의 IP 확인
- 현재 설정: 192.168.1.51 (DHCP 예약 권장)
Step 3: 웹 UI 확인
- 브라우저에서
http://192.168.1.51접속 - Device Information에서 펌웨어 버전, 튜너 상태 확인
- Channel Lineup에서 수신 가능한 채널 확인 가능
Step 4: 펌웨어 업데이트
- 웹 UI → System → Firmware → Check for Update
- 또는 SiliconDust 공식 앱(HDHomeRun) 사용
참고: HDHomeRun 자체에서 설정할 것은 거의 없습니다. 주요 설정은 모두 TVHeadend에서 수행합니다.
3. TVHeadend
3.1 역할
TVHeadend는 TV 스트리밍 서버 소프트웨어입니다.
- HDHomeRun 튜너를 네트워크로 자동 검색 및 제어
- 주파수(Mux) 스캔으로 채널 자동 검색
- 채널 매핑 및 번호 관리
- EPG(전자 프로그램 가이드) 수집 및 관리
- HTSP/HTTP 프로토콜로 Jellyfin에 라이브 스트림 제공
- 녹화 기능 (DVR)
- 스트리밍 프로파일 관리 (pass-through, 트랜스코딩)
3.2 Docker 설치
3.2.1 디렉토리 구조
/volume2/storage/docker/tvheadend/
├── compose.yaml # Docker Compose 설정
├── config/ # TVHeadend 설정 (볼륨 마운트)
│ ├── config # 메인 설정 파일
│ ├── accesscontrol/ # 접근 제어
│ ├── passwd/ # 사용자 인증
│ ├── channel/ # 채널 설정
│ │ └── config/ # 개별 채널 설정 파일 (UUID별)
│ ├── epggrab/ # EPG 수집 설정
│ │ └── config # EPG 모듈 설정
│ ├── input/
│ │ ├── dvb/
│ │ │ └── networks/ # DVB 네트워크 설정
│ │ │ └── {uuid}/
│ │ │ ├── config # 네트워크 설정
│ │ │ └── muxes/ # 주파수(Mux) 파일들
│ │ └── tvhdhomerun/
│ │ └── adapters/ # HDHomeRun 어댑터 설정
│ ├── profile/ # 스트리밍 프로파일
│ ├── picons/ # 채널 아이콘 (115개 PNG)
│ └── imagecache/ # 이미지 캐시
├── recordings/ # 녹화 저장 경로
└── epg2xml/ # EPG2XML 설정 (한국 EPG)
└── epg2xml.json # EPG 채널 매핑
3.2.2 compose.yaml
services:
tvheadend:
container_name: tvheadend
image: wiserain/tvheadend:latest
restart: always
network_mode: "host"
volumes:
- /volume2/storage/docker/tvheadend/config:/config
- /volume2/storage/docker/tvheadend/recordings:/recordings
- /volume2/storage/docker/tvheadend/epg2xml:/epg2xml
environment:
- PUID=0
- PGID=0
- TZ=Asia/Seoul
- TVH_URL='http://uhyung:*****@localhost:9981'
주요 설정 설명:
| 항목 | 값 | 설명 |
|---|---|---|
| image | wiserain/tvheadend:latest |
한국 EPG2XML 내장 이미지 |
| network_mode | host |
호스트 네트워크 사용 (HDHomeRun 자동 검색에 필요) |
| PUID/PGID | 0/0 | root 권한 (튜너 접근에 필요) |
| TZ | Asia/Seoul | 한국 시간대 |
| TVH_URL | 인증 URL | EPG2XML이 TVHeadend API 접근 시 사용 |
3.2.3 배포 명령
cd /volume2/storage/docker/tvheadend
docker compose up -d
3.3 웹 UI 접근
- URL:
http://192.168.1.99:9981 - 인증: uhyung / *****
- 포트: 9981 (HTTP), 9982 (HTSP)
3.4 튜너/어댑터 설정
설정 위치
- 웹 UI:
설정(Configuration)→TV 어댑터(TV adapters) - 설정 파일:
/config/input/tvhdhomerun/adapters/{uuid}
현재 설정
TVHeadend는 네트워크의 HDHomeRun을 자동으로 검색합니다.
| 항목 | 값 |
|---|---|
| HDHomeRun IP | 192.168.1.51 |
| 튜너 수 | 4개 (Tuner #0 ~ #3) |
| fe_override | ATSC-T |
| 모든 튜너 | 활성화(enabled) |
| OTA EPG | 활성화 |
설정 방법
- 웹 UI →
설정→TV 어댑터 - HDHomeRun이 자동 검색되어 나타남
- 각 튜너를 클릭하여
활성화체크 Fe Override를 ATSC-T로 설정 (한국 케이블)- 네트워크에 ko-Cable-8VSB 선택
- 저장
3.5 네트워크 설정
설정 위치
- 웹 UI:
설정→네트워크(Networks) - 설정 파일:
/config/input/dvb/networks/{uuid}/config
현재 설정
| 항목 | 값 | 설명 |
|---|---|---|
| 네트워크명 | ko-Cable-8VSB | 한국 케이블 8VSB 주파수 프리셋 |
| 제공자명 | D-Live | 딜라이브 케이블 |
| 클래스 | dvb_network_atsc_t | ATSC-T (지상파/케이블 8VSB) |
| 자동검색 | 활성화 | 새 Mux/서비스 자동 검색 |
| SID→채널번호 | 활성화 | Service ID를 채널 번호로 사용 |
| 로컬타임 | 540 (UTC+9) | 한국 시간대 |
설정 방법
- 웹 UI →
설정→네트워크 추가(Add)→ATSC-T Network선택- 네트워크명:
ko-Cable-8VSB Pre-defined muxes에서 ko-Cable-8VSB 선택 (한국 케이블 주파수 프리셋)Provider network name: D-LiveSkip initial scan체크 해제 (첫 스캔 시)- 저장
3.6 Mux 스캔 및 서비스 매핑
개념
- Mux (Multiplex): 하나의 주파수에 여러 채널이 묶여 있는 단위
- 서비스: Mux 안의 개별 채널 (예: KBS1, MBC 등)
현재 상태
- Mux: 157개 설정됨
- 매핑된 채널: 117개
스캔 방법
- 네트워크 설정 후, TVHeadend가 자동으로 Mux 스캔 시작
설정→Mux탭에서 스캔 진행률 확인- 스캔 완료 후
서비스탭에서 발견된 채널 목록 확인 - 원하는 서비스 선택 →
채널로 매핑(Map selected services to channels)클릭
참고: 스캔에 시간이 걸립니다 (157개 Mux). 진행률은 Mux 탭의
Scan Result컬럼에서 확인하세요.
3.7 채널 매핑
설정 위치
- 웹 UI:
설정→채널(Channels)탭 - 설정 파일:
/config/channel/config/{uuid}(채널별 JSON 파일)
채널 설정 파일 예시
{
"enabled": true,
"name": "KBS1",
"number": 9,
"icon": "https://image.tving.com/upload/channel/logo/KBS1.png",
"epgauto": true,
"services": ["{service_uuid}"]
}
설정 방법
서비스탭에서 매핑 후채널탭으로 이동- 채널명, 채널 번호 수정 가능
- 불필요한 채널 비활성화 또는 삭제
- 채널 아이콘 URL 지정 가능
3.8 EPG (전자 프로그램 가이드) 설정
3.8.1 EPG 수집 모듈
| 모듈 | 상태 | 우선순위 | 설명 |
|---|---|---|---|
| tv_grab_kr_kt | 활성화 | 3 | KT EPG (epg2xml) - 주력 |
| tv_grab_klive | 활성화 | 3 | KLIVE EPG |
| psip | 활성화 | 1 | ATSC OTA EPG |
| eit | 활성화 | 1 | DVB OTA EPG |
| tv_grab_kr_sk | 비활성화 | 3 | SK EPG (사이트 개편으로 중단) |
설정 위치
- 웹 UI:
설정→EPG Grabber Modules - 설정 파일:
/config/epggrab/config
EPG Cron 스케줄
Internal EPG: 4 */12 * * * (매 12시간마다)
OTA EPG: 4 2 * * * (매일 02:04)
4 14 * * * (매일 14:04)
OTA 타임아웃: 600초
3.8.2 EPG2XML 설정
EPG2XML은 한국 IPTV/케이블 사업자의 EPG 데이터를 XMLTV 형식으로 변환하는 도구입니다.
wiserain/tvheadend 이미지에 내장되어 있습니다.
설정 파일: /epg2xml/epg2xml.json
{
"GLOBAL": {
"ENABLED": true,
"FETCH_LIMIT": 2,
"ID_FORMAT": "{ServiceId}.{Source.lower()}",
"ADD_REBROADCAST_TO_TITLE": false,
"ADD_EPNUM_TO_TITLE": true,
"ADD_DESCRIPTION": true,
"ADD_CHANNEL_ICON": true
},
"KT": {
"MY_CHANNELS": [
{"Name": "KBS1", "No": "9", "ServiceId": "9", "Category": "지상파"},
{"Name": "KBS2", "No": "7", "ServiceId": "7", "Category": "지상파"},
{"Name": "MBC", "No": "11", "ServiceId": "11", "Category": "지상파"},
{"Name": "SBS", "No": "5", "ServiceId": "5", "Category": "지상파"},
...
]
}
}
| 설정 항목 | 값 | 설명 |
|---|---|---|
| EPG 소스 | KT | D-Live는 epg2xml 미지원, KT로 대체 |
| FETCH_LIMIT | 2 | 2일치 EPG 수집 |
| ADD_EPNUM_TO_TITLE | true | 제목에 회차 번호 추가 |
| ADD_DESCRIPTION | true | 프로그램 설명 포함 |
| MY_CHANNELS | 95개 | D-Live 채널과 매칭된 KT 채널 ID |
EPG 채널 매핑 방법
D-Live 케이블은 epg2xml에서 직접 지원하지 않으므로, KT의 EPG 데이터를 사용합니다.
/epg2xml/epg2xml.json편집KT→MY_CHANNELS배열에 채널 추가Name,No,ServiceId는 KT 기준, TVHeadend 채널명과 일치시킬 것- TVHeadend 컨테이너 재시작 후 EPG Grabber 실행
3.9 스트리밍 프로파일
설정 위치
- 웹 UI:
설정→스트리밍 프로파일(Stream Profiles) - 설정 파일:
/config/profile/{uuid}
현재 설정
| 프로파일명 | 타입 | 상태 | 용도 |
|---|---|---|---|
| pass | MPEG-TS Pass-thru | 활성화 | Jellyfin 연결용 (원본 전달) |
| htsp | HTSP | 활성화 | HTSP 기본 |
| webtv-h264-vorbis-mp4 | Transcode | 비활성화 | - |
| webtv-vp8-vorbis-webm | Transcode | 비활성화 | - |
| webtv-h264-aac-mpegts | Transcode | 비활성화 | - |
| webtv-h264-aac-matroska | Transcode | 비활성화 | - |
핵심: Jellyfin에서
pass프로파일을 사용하면 TVHeadend는 원본 스트림을 그대로 전달하고, 트랜스코딩은 Jellyfin이 담당합니다. TVHeadend의 CPU 부하를 줄이고 Jellyfin의 유연한 트랜스코딩을 활용할 수 있습니다.
3.10 채널 아이콘 (Picons)
설정 위치
- 파일:
/config/picons/디렉토리 (115개 PNG) - 웹 UI:
설정→일반(General)→Base Config
현재 설정
| 항목 | 값 | 설명 |
|---|---|---|
| chiconpath | 빈 문자열 | 채널 아이콘 자동 생성 비활성화 |
| piconpath | 빈 문자열 | Picon 자동 생성 비활성화 |
| prefer_picon | false | Picon 우선 사용 안 함 |
주의:
chiconpath/piconpath를 설정하면 TVHeadend가 자동으로picon://URL을 생성합니다. 수동으로 아이콘을 관리하는 경우 반드시 비활성화하세요.
아이콘 소스
- WAVVE CDN (
image.wavve.com) - TVING CDN (
image.tving.com) - imgur (GitHub epg2xml Channel.json 참조)
- 각 채널 공식 홈페이지
3.11 인증 및 접근 제어
설정 위치
- 웹 UI:
설정→접근 항목(Access Entries),사용자(Users) - 설정 파일:
/config/passwd/,/config/accesscontrol/
현재 설정
| 항목 | uhyung | 기본(*) |
|---|---|---|
| 스트리밍 | basic, advanced, htsp | basic, advanced, htsp |
| DVR | 전체 | 전체 |
| 웹 UI | 허용 | 허용 |
| 관리자 | 예 | 예 |
| 접근 범위 | 0.0.0.0/0 (전체) | 0.0.0.0/0 (전체) |
3.12 메인 설정 파일 주요 항목
설정 파일: /config/config
| 항목 | 값 | 설명 |
|---|---|---|
| server_name | Tvheadend | 서버명 |
| language_ui | kor | UI 언어 (한국어) |
| theme_ui | access | 테마 |
| uilevel | 2 | Expert 모드 |
| language | ["kor", "eng"] | 컨텐츠 언어 |
| hdhomerun_ip | 192.168.1.51 | HDHomeRun IP |
| local_ip | 192.168.1.99 | NAS IP |
| epg_compress | true | EPG 압축 |
| epg_window | 86400 | EPG 윈도우 (24시간) |
4. Jellyfin
4.1 역할
Jellyfin은 미디어 서버 소프트웨어입니다.
- TVHeadend와 연동하여 라이브 TV 시청 제공
- 클라이언트 환경에 맞게 실시간 트랜스코딩 (H.264 등)
- 사용자별 접근 제어 및 비트레이트 제한
- 웹 브라우저, iOS/Android 앱, TV 앱, Infuse 등 다양한 클라이언트 지원
- VOD 미디어 라이브러리 관리 (영화, TV 시리즈 등)
- EPG 가이드 표시 및 프로그램 검색
4.2 Docker 설치
4.2.1 디렉토리 구조
/volume2/storage/docker/jellyfin/
├── compose.yaml # Docker Compose 설정
├── config/ # Jellyfin 설정 (볼륨 마운트)
│ ├── system.xml # 시스템 설정
│ ├── network.xml # 네트워크 설정
│ ├── encoding.xml # 인코딩/트랜스코딩 설정
│ ├── livetv.xml # 라이브 TV 설정
│ ├── metadata.xml # 메타데이터 설정
│ ├── logging.default.json # 로깅 설정
│ ├── data/
│ │ ├── data/
│ │ │ ├── jellyfin.db # 메인 DB
│ │ │ └── library.db # 라이브러리 DB
│ │ ├── plugins/
│ │ │ ├── TVHeadend_12.0.0.0/ # TVHeadend 플러그인
│ │ │ ├── InfuseSync_1.5.0.0/ # InfuseSync 플러그인
│ │ │ └── configurations/ # 플러그인 설정
│ │ └── transcodes/ # 트랜스코딩 임시 파일
│ └── users/ # 사용자 프로필
├── fonts/ # 자막 폰트
└── cache/ # 캐시
4.2.2 compose.yaml
version: "2.1"
services:
jellyfin:
image: lscr.io/linuxserver/jellyfin:latest
container_name: jellyfin
environment:
- PUID=1026
- PGID=100
- TZ=Asia/Seoul
- JELLYFIN_PublishedServerUrl=192.168.1.99
volumes:
- /volume2/storage/docker/jellyfin/config:/config
- /volume2/video/TV:/data/tvshows
- /volume2/video/movies:/data/movies
- /volume2/video/adult:/data/adult
- /volume2/video/adult2:/data/adult2
- /volume2/video/adult3:/data/adult3
- /volume2/storage/docker/jellyfin/fonts:/usr/share/fonts
ports:
- 8096:8096
- 8920:8920
restart: unless-stopped
주요 설정 설명:
| 항목 | 값 | 설명 |
|---|---|---|
| image | lscr.io/linuxserver/jellyfin:latest |
LinuxServer.io Jellyfin 이미지 |
| PUID/PGID | 1026/100 | NAS 사용자 권한 |
| PublishedServerUrl | 192.168.1.99 | 클라이언트에 알려줄 서버 주소 |
| 8096 | HTTP 포트 | 웹 UI 및 API |
| 8920 | HTTPS 포트 | 보안 접속 |
4.2.3 배포 명령
cd /volume2/storage/docker/jellyfin
docker compose up -d
4.3 TVHeadend 플러그인 설정
설치 방법
- Jellyfin 웹 UI →
관리자(Dashboard)→플러그인(Plugins)→카탈로그(Catalog) - Live TV 카테고리에서
TVHeadend검색 - 설치 후 Jellyfin 재시작:
docker restart jellyfin
설정 위치
- 웹 UI:
관리자→플러그인→TVHeadend→ 설정 - 설정 파일:
/config/data/plugins/configurations/TVHeadEnd.xml
현재 설정
<PluginConfiguration>
<TVH_ServerName>192.168.1.99</TVH_ServerName>
<HTTP_Port>9981</HTTP_Port>
<HTSP_Port>9982</HTSP_Port>
<WebRoot>/</WebRoot>
<Username>uhyung</Username>
<Password>*****</Password>
<Priority>5</Priority>
<Profile>pass</Profile>
<ChannelType>Ignore</ChannelType>
<EnableSubsMaudios>true</EnableSubsMaudios>
<ForceDeinterlace>true</ForceDeinterlace>
</PluginConfiguration>
| 항목 | 값 | 설명 |
|---|---|---|
| TVH_ServerName | 192.168.1.99 | TVHeadend 서버 IP |
| HTTP_Port | 9981 | TVHeadend HTTP 포트 |
| HTSP_Port | 9982 | TVHeadend HTSP 포트 |
| Profile | pass | MPEG-TS Pass-thru (원본 전달) |
| Priority | 5 | 스트리밍 우선순위 |
| ForceDeinterlace | true | 인터레이스 영상 강제 디인터레이스 |
| ChannelType | Ignore | 채널 타입 무시 (전체 채널 표시) |
4.4 인코딩/트랜스코딩 설정
설정 위치
- 웹 UI:
관리자→재생(Playback)→트랜스코딩(Transcoding) - 설정 파일:
/config/encoding.xml
현재 설정
| 항목 | 값 | 설명 |
|---|---|---|
| HardwareAccelerationType | none | 하드웨어 가속 없음 (Xeon D-1527에 iGPU 없음) |
| EncoderPreset | faster | 인코딩 속도/품질 균형 |
| H264Crf | 23 | H.264 품질 (낮을수록 고품질) |
| H265Crf | 28 | H.265 품질 |
| DeinterlaceMethod | yadif | 디인터레이스 방식 |
| DeinterlaceDoubleRate | true | 60fps 디인터레이스 |
| EnableThrottling | true | 트랜스코딩 쓰로틀링 (CPU 절약) |
| ThrottleDelaySeconds | 180 | 쓰로틀 시작 딜레이 |
| EnableSegmentDeletion | true | 재생 완료 세그먼트 삭제 |
| SegmentKeepSeconds | 120 | 세그먼트 유지 시간 |
| MaxMuxingQueueSize | 2048 | FFmpeg 먹싱 큐 크기 |
인코더 프리셋 참고
ultrafast → superfast → veryfast → faster → fast → medium → slow → slower → veryslow
빠름/저품질 ←────────────────────────────────────────────────→ 느림/고품질
현재
faster: CPU 소프트웨어 인코딩에서 실시간 트랜스코딩이 가능하면서,veryfast보다 10~15% 화질이 향상됩니다.
트랜스코딩 성능 (Xeon D-1527 기준)
| 프리셋 | 720p 동시 스트림 | 1080p 동시 스트림 |
|---|---|---|
| veryfast | 3~4개 | 2~3개 |
| faster (현재) | 2~3개 | 1~2개 |
| fast | 1~2개 | 1개 |
4.5 사용자 관리 및 비트레이트 제한
설정 위치
- 웹 UI:
관리자→사용자(Users)→ 사용자 선택 → 편집
현재 사용자 (10명)
| 사용자 | RemoteClientBitrateLimit |
|---|---|
| uhyung | 4 Mbps |
| cuy658, elfman, ho918, jia, leesj | 4 Mbps |
| minah, monika, monika0101, nan0767 | 4 Mbps |
4 Mbps는 YouTube 720p와 동등한 수준입니다. 외부(모바일/와이파이)에서 끊김 없이 시청 가능합니다.
비트레이트 제한 변경 방법
웹 UI:
관리자→사용자→ 사용자 클릭원격 클라이언트 비트레이트 제한항목 수정- 저장
API:
# 인증 토큰 획득
TOKEN=$(curl -s -X POST "http://192.168.1.99:8096/Users/AuthenticateByName" \
-H "Content-Type: application/json" \
-H 'X-Emby-Authorization: MediaBrowser Client="CLI", Device="CLI", DeviceId="cli", Version="1.0"' \
-d '{"Username":"uhyung","Pw":"*****"}' | jq -r '.AccessToken')
# 사용자 목록 조회
curl -s "http://192.168.1.99:8096/Users" \
-H "X-Emby-Token: $TOKEN" | jq '.[].Name'
4.6 채널 아이콘 설정
문제점
TVHeadend의 HTSP 프로토콜은 채널 아이콘을 Jellyfin으로 전달하지 않습니다.
file:///경로 → 전달 불가- HTTP URL → 25바이트 플레이스홀더만 전달
해결: Jellyfin API 직접 업로드
# 1. 인증 토큰 획득 (위 API 참조)
# 2. 채널 ID 조회
curl -s "http://192.168.1.99:8096/LiveTv/Channels?Limit=200" \
-H "X-Emby-Token: $TOKEN" | jq '.Items[] | {Name, Id}'
# 3. 이미지 업로드 (base64 인코딩된 PNG)
CHANNEL_ID="채널ID"
BASE64=$(base64 < /path/to/channel_logo.png)
curl -X POST "http://192.168.1.99:8096/Items/$CHANNEL_ID/Images/Primary" \
-H "X-Emby-Token: $TOKEN" \
-H "Content-Type: image/png" \
-d "$BASE64"
# HTTP 204 = 성공
또는 Jellyfin UI에서 수동 업로드:
- 라이브 TV → 채널 선택 → 이미지 편집
- 이미지 + 클릭 → PNG 파일 선택
현재 상태
- 113/117 채널 로고 적용 완료
- 미적용 4개: 지역채널, 컬쳐플러스, 채널이엠, 채널액션 (공식 로고 미발견)
- 아이콘 파일 보관:
/volume2/storage/docker/tvheadend/config/picons/(115개 PNG)
4.7 네트워크/외부 접근 설정
설정 위치
- 웹 UI:
관리자→네트워킹(Networking) - 설정 파일:
/config/network.xml
현재 설정
| 항목 | 값 | 설명 |
|---|---|---|
| HTTP 포트 | 8096 | 기본 웹 포트 |
| HTTPS 포트 | 8920 | 보안 포트 |
| 원격 접근 | 활성화 | 외부 접속 허용 |
| UPnP | 활성화 | 자동 포트포워딩 |
| IPv6 | 비활성화 | - |
| PublishedServerUrl | 192.168.1.99 | 클라이언트에 알려줄 서버 주소 |
외부 접근을 위한 공유기 포트포워딩
| 외부 포트 | 내부 IP | 내부 포트 | 프로토콜 |
|---|---|---|---|
| 8096 | 192.168.1.99 | 8096 | TCP |
| 8920 (선택) | 192.168.1.99 | 8920 | TCP |
4.8 시스템 설정
설정 파일: /config/system.xml
| 항목 | 값 | 설명 |
|---|---|---|
| 메타데이터 언어 | ko (한국어) | 영화/드라마 정보 한국어 |
| 국가 코드 | KR | 한국 |
| UI 문화권 | ko | UI 한국어 |
| 로그 보관 | 3일 | - |
| 활동 로그 보관 | 30일 | - |
| QuickConnect | Available | 빠른 연결 활성화 |
4.9 플러그인 목록
| 플러그인 | 버전 | 설명 |
|---|---|---|
| TVHeadend | 12.0.0.0 | 라이브 TV (HTSP 연결) |
| InfuseSync | 1.5.0.0 | Infuse 앱 동기화 |
| TMDB | 기본 | 영화/드라마 메타데이터 |
| OMDB | 기본 | 영화 메타데이터 |
| MusicBrainz | 기본 | 음악 메타데이터 |
| Studio Images | 기본 | 스튜디오 로고 |
5. 전체 설정 순서 (Step-by-Step)
처음부터 설정하는 경우의 전체 순서입니다.
Phase 1: 하드웨어 준비
Step 1: 물리적 연결
- 케이블 벽체 단자 → 동축케이블 → HDHomeRun CABLE IN 포트
- LAN 케이블 → HDHomeRun ETHERNET 포트 → 공유기/스위치
- 전원 어댑터 연결
Step 2: HDHomeRun IP 확인
- 공유기 관리 페이지에서 HDHomeRun IP 확인
http://{IP}접속하여 정상 동작 확인- DHCP 예약 설정으로 IP 고정
Phase 2: TVHeadend 설치 및 설정
Step 3: TVHeadend Docker 배포
mkdir -p /volume2/storage/docker/tvheadend/{config,recordings,epg2xml}
# compose.yaml 작성 (3.2.2 참조)
cd /volume2/storage/docker/tvheadend
docker compose up -d
Step 4: TVHeadend 초기 설정
http://192.168.1.99:9981접속- 초기 설정 마법사: 언어(한국어), EPG 언어(kor, eng), 관리자 계정 생성
- Expert 모드로 전환 (
uilevel: 2)
Step 5: 튜너 연결
설정→TV 어댑터→ HDHomeRun 자동 검색 확인- 4개 튜너 모두 활성화
fe_override: ATSC-T 설정- 각 튜너에 네트워크 할당
Step 6: 네트워크 및 Mux 스캔
설정→네트워크→추가→ATSC-T Network- Pre-defined muxes: ko-Cable-8VSB 선택
- Provider name: D-Live
- 저장 → 자동 Mux 스캔 시작 (157개 Mux)
Step 7: 서비스 → 채널 매핑
설정→서비스탭에서 원하는 서비스 선택채널로 매핑클릭채널탭에서 채널명, 번호 수정
Step 8: EPG 설정
/epg2xml/epg2xml.json편집 (KT 채널 매핑 추가)설정→EPG Grabber Modules→tv_grab_kr_kt활성화docker restart tvheadend- EPG 수집 확인
Step 9: 스트리밍 프로파일 설정
설정→스트리밍 프로파일pass프로파일 활성화 확인- 불필요한
webtv-*프로파일 비활성화
Step 10: 채널 아이콘 다운로드
mkdir -p /config/picons- 채널 로고 PNG 파일 다운로드 (파일명: 채널명.png)
chiconpath/piconpath비활성화
Phase 3: Jellyfin 설치 및 설정
Step 11: Jellyfin Docker 배포
mkdir -p /volume2/storage/docker/jellyfin/{config,fonts,cache}
# compose.yaml 작성 (4.2.2 참조)
cd /volume2/storage/docker/jellyfin
docker compose up -d
Step 12: Jellyfin 초기 설정
http://192.168.1.99:8096접속- 초기 마법사: 관리자 계정, 메타데이터 언어(한국어), 국가(대한민국)
Step 13: TVHeadend 플러그인 설치
관리자→플러그인→카탈로그→ TVHeadend 설치docker restart jellyfin- 플러그인 설정: TVH Server, Port, Username/Password, Profile: pass
- 저장 → 라이브 TV 채널 목록 확인
Step 14: 인코딩 최적화
관리자→재생→트랜스코딩- Hardware Acceleration: None
- Encoder Preset: faster
- Deinterlace: yadif
- Segment Deletion: 활성화 (120초)
Step 15: 사용자 관리
관리자→사용자→ 사용자 추가- RemoteClientBitrateLimit: 4000000 (4Mbps)
- 라이브 TV 접근 권한 허용
Step 16: 채널 아이콘 업로드
- 방법 A: Jellyfin API로 base64 PNG 업로드 (4.6 참조)
- 방법 B: Jellyfin UI → 채널 선택 → 이미지 편집 → PNG 선택
Step 17: 외부 접근 설정
관리자→네트워킹→ 원격 접근 허용- 공유기 포트포워딩: 외부 8096 → 192.168.1.99:8096
Phase 4: 검증
Step 18: 최종 테스트
- LAN에서 라이브 TV 재생 테스트
- 외부 네트워크에서 재생 테스트
- EPG 프로그램 가이드 표시 확인
- 채널 아이콘 표시 확인
- 동시 시청 테스트 (CPU 부하 확인)
6. 트러블슈팅 및 참고사항
6.1 자주 발생하는 문제
HTSP로 채널 아이콘이 Jellyfin에 표시되지 않음
- 원인: TVHeadend HTSP 프로토콜이 아이콘 데이터를 Jellyfin으로 전달하지 않음
- 해결: Jellyfin API로 직접 업로드 (4.6 참조)
TVHeadend 설정 변경이 반영되지 않음
- 원인: TVHeadend는 설정 파일을 메모리에 캐싱
- 해결: 디스크에서 직접 파일을 수정한 경우 컨테이너 재시작 필요
docker restart tvheadend
외부에서 버퍼링/끊김 발생
- 업로드 속도 확인 (최소 4Mbps 이상)
- RemoteClientBitrateLimit 낮추기 (예: 2Mbps)
- EncoderPreset을
veryfast로 변경 (CPU 부하 감소)
Mux 스캔 시 채널이 검색되지 않음
- HDHomeRun 웹 UI (
http://192.168.1.51)에서 연결 상태 확인 - 동축 케이블 연결 확인
fe_override가 ATSC-T로 설정되어 있는지 확인- 올바른 주파수 프리셋(ko-Cable-8VSB) 선택 확인
EPG가 표시되지 않음
epg2xml.json의 MY_CHANNELS 매핑 확인tv_grab_kr_kt모듈 활성화 확인- TVHeadend 재시작 후 EPG Grabber 수동 실행
- Jellyfin에서
라이브 TV→가이드 새로고침
6.2 하드웨어 트랜스코딩 관련
DS3617xs의 Xeon D-1527은 iGPU가 없어 하드웨어 트랜스코딩이 불가능합니다.
- Intel QSV, VAAPI 모두 사용 불가
/dev/dri/장치가 존재하지 않음- CPU 소프트웨어 인코딩만 가능 (동시 1080p 1~2스트림)
6.3 백업 방법
# TVHeadend 설정 백업 (채널, EPG, 프로파일 모두 포함)
cd /volume2/storage/docker/tvheadend
tar czf /volume2/storage/tvheadend-backup-$(date +%Y%m%d).tar.gz config/ epg2xml/
# Jellyfin 설정 백업
cd /volume2/storage/docker/jellyfin
tar czf /volume2/storage/jellyfin-backup-$(date +%Y%m%d).tar.gz config/
중요:
docker commit은 볼륨 데이터를 포함하지 않습니다. 반드시 볼륨을 별도로 백업하세요.
6.4 유용한 명령어
# Docker 컨테이너 상태 확인
docker ps --filter name=tvheadend --filter name=jellyfin
# 로그 확인
docker logs -f tvheadend --tail 100
docker logs -f jellyfin --tail 100
# 컨테이너 재시작
docker restart tvheadend
docker restart jellyfin
# Jellyfin API로 서버 재시작
curl -X POST "http://192.168.1.99:8096/System/Restart" \
-H "X-Emby-Token: $TOKEN"
# TVHeadend API 채널 목록 조회
curl -s "http://192.168.1.99:9981/api/channel/grid?limit=200" \
-u "uhyung:*****" | jq '.entries[].name'
# Jellyfin API 채널 목록 조회
curl -s "http://192.168.1.99:8096/LiveTv/Channels?Limit=200" \
-H "X-Emby-Token: $TOKEN" | jq '.Items[].Name'
6.5 주요 포트 정리
| 포트 | 서비스 | 프로토콜 | 용도 |
|---|---|---|---|
| 9981 | TVHeadend | HTTP | 웹 UI, API |
| 9982 | TVHeadend | HTSP | Jellyfin 스트리밍 연결 |
| 8096 | Jellyfin | HTTP | 웹 UI, API, 클라이언트 |
| 8920 | Jellyfin | HTTPS | 보안 접속 |
7. 설정 파일 경로 총정리
TVHeadend
| 파일/디렉토리 | 호스트 경로 | Docker 내부 경로 | 설명 |
|---|---|---|---|
| Docker Compose | .../tvheadend/compose.yaml |
- | Docker 설정 |
| 메인 설정 | .../tvheadend/config/config |
/config/config |
서버 전체 설정 |
| 채널 설정 | .../config/channel/config/ |
/config/channel/config/ |
채널별 JSON |
| 네트워크 설정 | .../config/input/dvb/networks/{uuid}/config |
/config/input/... |
DVB 네트워크 |
| Mux 파일 | .../config/input/dvb/networks/{uuid}/muxes/ |
/config/input/... |
주파수 (157개) |
| 튜너 설정 | .../config/input/tvhdhomerun/adapters/{uuid} |
/config/input/... |
HDHomeRun |
| EPG 설정 | .../config/epggrab/config |
/config/epggrab/config |
EPG 모듈 |
| 프로파일 | .../config/profile/ |
/config/profile/ |
스트리밍 프로파일 |
| 사용자 인증 | .../config/passwd/ |
/config/passwd/ |
비밀번호 |
| 접근 제어 | .../config/accesscontrol/ |
/config/accesscontrol/ |
ACL |
| 채널 아이콘 | .../config/picons/ |
/config/picons/ |
PNG (115개) |
| EPG2XML | .../epg2xml/epg2xml.json |
/epg2xml/epg2xml.json |
한국 EPG 매핑 |
Jellyfin
| 파일/디렉토리 | 호스트 경로 | Docker 내부 경로 | 설명 |
|---|---|---|---|
| Docker Compose | .../jellyfin/compose.yaml |
- | Docker 설정 |
| 시스템 설정 | .../jellyfin/config/system.xml |
/config/system.xml |
서버 설정 |
| 네트워크 설정 | .../jellyfin/config/network.xml |
/config/network.xml |
네트워크 |
| 인코딩 설정 | .../jellyfin/config/encoding.xml |
/config/encoding.xml |
트랜스코딩 |
| 라이브 TV | .../jellyfin/config/livetv.xml |
/config/livetv.xml |
라이브 TV |
| TVHeadend 플러그인 | .../config/data/plugins/configurations/TVHeadEnd.xml |
/config/data/... |
플러그인 설정 |
| 메인 DB | .../config/data/data/jellyfin.db |
/config/data/data/... |
사용자/설정 |
| 라이브러리 DB | .../config/data/data/library.db |
/config/data/data/... |
미디어 메타데이터 |
호스트 경로 기준:
/volume2/storage/docker/(.../로 축약)
문서 작성일: 2026-03-16 서버 환경: Synology DS3617xs / Xeon D-1527 / 48GB RAM 소프트웨어 버전: TVHeadend 4.3-2442, Jellyfin 10.10.6