Merge branch 'master' into patch-1

This commit is contained in:
Carol Ouellet
2026-08-04 17:09:47 -04:00
committed by GitHub
111 changed files with 8132 additions and 4431 deletions
+1 -1
View File
@@ -3,7 +3,7 @@
{
"name": "Node.js & TypeScript",
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
"image": "mcr.microsoft.com/devcontainers/typescript-node:4-22-bookworm",
"image": "mcr.microsoft.com/devcontainers/typescript-node:5-22-bookworm",
"workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
"postAttachCommand": "cat .vscode/extensions.json | jq -r .recommendations[] | xargs -n 1 code --install-extension",
+5
View File
@@ -0,0 +1,5 @@
blank_issues_enabled: true
contact_links:
- name: Jellyfin contact
url: https://jellyfin.org/contact/
about: Our community is ready to help you get started with Jellyfin
@@ -0,0 +1,56 @@
name: Incorrect documentation
description: Report outdated or incorrect documentation.
labels:
- bug
- documentation
body:
- type: checkboxes
id: before-posting
attributes:
label: 'This issue respects the following points:'
description: All conditions are **required**.
options:
- label: This issue is **not** already reported on [GitHub](https://github.com/jellyfin/jellyfin.org/issues?q=is%3Aopen+is%3Aissue) _(I've searched it)_.
required: true
- label: I agree to follow Jellyfin's [Code of Conduct](https://jellyfin.org/docs/general/community-standards.html#code-of-conduct).
required: true
- label: This report addresses only a single issue; If you encounter multiple issues, kindly create separate reports for each one.
required: true
- type: markdown
attributes:
value: |
## Documentation information
- type: textarea
id: description
attributes:
label: Describe the incorrect documentation
description: |
A clear and exact description of the incorrect documentation.
placeholder: |
Under `Post-Install Setup > Networking`, Port 8096 is listed as the default port for HTTP, but it should be XYZ.
This came with the release of Jellyfin 10.1.1, where the default port was changed to XYZ.
validations:
required: true
- type: textarea
id: suggestion
attributes:
label: suggestion
description: |
Suggest how to correct the documentation.
placeholder: |
The default port for HTTP should be XYZ.
validations:
required: true
- type: markdown
attributes:
value: |
## Additional
- type: input
id: other-sources
attributes:
label: Other sources
description: Please link the related forum topics or chat messages that prompted you open this issue.
placeholder: https://forum.jellyfin.org/…
validations:
required: false
@@ -0,0 +1,55 @@
name: New/expand documentation
description: Request new documentation for a feature or functionality that is missing.
labels:
- enhancement
- documentation
body:
- type: checkboxes
id: before-posting
attributes:
label: 'This issue respects the following points:'
description: All conditions are **required**.
options:
- label: This issue is **not** already reported on [GitHub](https://github.com/jellyfin/jellyfin.org/issues?q=is%3Aopen+is%3Aissue) _(I've searched it)_.
required: true
- label: I agree to follow Jellyfin's [Code of Conduct](https://jellyfin.org/docs/general/community-standards.html#code-of-conduct).
required: true
- label: This report addresses only a single issue; If you encounter multiple issues, kindly create separate reports for each one.
required: true
- type: markdown
attributes:
value: |
## Documentation information
- type: textarea
id: description
attributes:
label: Describe the missing documentation
description: |
A clear and exact description of the missing documentation.
placeholder: |
There is no documentation on how to install Jellyfin on Docker. This would be helpful for ...
validations:
required: true
- type: textarea
id: reasoning
attributes:
label: reasoning
description: |
Explain why this documentation is needed.
placeholder: |
This documentation would help users who are new to Docker and want to run Jellyfin in a container.
validations:
required: true
- type: markdown
attributes:
value: |
## Additional
- type: input
id: other-sources
attributes:
label: Other sources
description: Please link the related forum topics or chat messages that prompted you open this issue.
placeholder: https://forum.jellyfin.org/…
validations:
required: false
+66
View File
@@ -0,0 +1,66 @@
name: Website problem or improvement
description: Report a website bug, rendering issue, navigation problem, search issue, accessibility concern, or a suggestion for improvement.
labels:
- bug
- enhancement
body:
- type: checkboxes
id: before-posting
attributes:
label: 'This issue respects the following points:'
description: All conditions are **required**.
options:
- label: This issue is **not** already reported on [GitHub](https://github.com/jellyfin/jellyfin.org/issues?q=is%3Aopen+is%3Aissue) _(I've searched it)_.
required: true
- label: I agree to follow Jellyfin's [Code of Conduct](https://jellyfin.org/docs/general/community-standards.html#code-of-conduct).
required: true
- label: This report addresses only a single issue; If you encounter multiple issues, kindly create separate reports for each one.
required: true
- type: markdown
attributes:
value: |
## Website information
- type: textarea
id: description
attributes:
label: Describe the website issue or improvement
description: |
A clear and exact description of the problem or the improvement you would like to see.
placeholder: |
The mobile navigation menu overlaps the page content on the downloads page and cannot be closed.
The search box should return relevant results for docs and blog posts.
validations:
required: true
- type: textarea
id: location
attributes:
label: Where does it happen?
description: |
Specify the affected page, section, or component.
placeholder: |
The home page hero section, the downloads page, the top navigation, the search bar, etc.
validations:
required: true
- type: textarea
id: expectation
attributes:
label: What is the expected behavior?
description: |
Explain what should happen instead or how the improvement should work.
placeholder: |
The menu should open and close correctly, and the search should return useful results without breaking the page.
validations:
required: true
- type: markdown
attributes:
value: |
## Additional
- type: input
id: other-sources
attributes:
label: Other sources
description: Please link any related forum topics, screenshots, or chat messages that prompted you to open this issue.
placeholder: https://forum.jellyfin.org/…
validations:
required: false
-48
View File
@@ -1,48 +0,0 @@
name: Build
on:
workflow_call:
inputs:
ref:
required: true
type: string
upload-pages-artifact:
required: false
type: boolean
default: false
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
ref: ${{ inputs.ref }}
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with:
node-version: 20
- name: Configure Pages
if: inputs.upload-pages-artifact
uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5.0.0
- name: Run build
run: |
npm ci --no-audit
npm run build
- name: Upload artifact
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: jellyfin-org__build
path: build
# Manual artifact creation because upload-pages-artifact v4 excludes dotfiles
# https://github.com/actions/upload-pages-artifact/issues/129
- name: Create pages artifact
if: inputs.upload-pages-artifact
run: tar --dereference --hard-dereference --directory build -cvf "$RUNNER_TEMP/artifact.tar" --exclude=.git --exclude=.github .
- name: Upload pages artifact
if: inputs.upload-pages-artifact
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: github-pages
path: ${{ runner.temp }}/artifact.tar
retention-days: 1
+15 -88
View File
@@ -5,102 +5,29 @@ concurrency:
cancel-in-progress: true
on:
pull_request_target:
pull_request:
push:
branches: [master]
jobs:
build:
uses: ./.github/workflows/__build.yml
permissions: {}
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
upload-pages-artifact: ${{ github.event_name == 'push' && github.repository == 'jellyfin/jellyfin.org' }}
deploy:
if: github.event_name == 'push' && github.repository == 'jellyfin/jellyfin.org'
name: Deploy to GitHub Pages
name: Build
runs-on: ubuntu-latest
permissions:
pages: write
id-token: write
concurrency: build-deploy-pages
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
contents: read
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5
publish:
if: github.event_name != 'push' && github.repository == 'jellyfin/jellyfin.org'
name: Deploy to Cloudflare Pages
runs-on: ubuntu-latest
needs: build
steps:
- name: Add comment
uses: thollander/actions-comment-pull-request@24bffb9b452ba05a4f3f77933840a6a841d1b32b # v3.0.1
if: github.event_name == 'pull_request_target'
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
github-token: ${{ secrets.JF_BOT_TOKEN }}
message: |
## Cloudflare Pages deployment
| **Latest commit** | <code>${{ github.event.pull_request.head.sha || github.sha }}</code> |
|-------------------|:-:|
| **Status** | 🔄 Deploying... |
| **Preview URL** | Not available |
| **Type** | 🔀 Preview |
pr-number: ${{ github.event.pull_request.number }}
comment-tag: CFPages-deployment
mode: recreate
- name: Download workflow artifact
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
ref: ${{ github.event.pull_request.head.sha || github.sha }}
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: .nvmrc
- name: Run build
run: |
npm ci --no-audit
npm run build
- name: Upload artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: jellyfin-org__build
path: build
- name: Publish to Cloudflare
id: cf
uses: cloudflare/wrangler-action@da0e0dfe58b7a431659754fdf3f186c529afbe65 # v3.14.1
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: pages deploy build --project-name=jellyfin-org --branch=${{
(github.event_name != 'pull_request_target' || github.event.pull_request.head.repo.full_name == github.repository)
&& (github.event.pull_request.head.ref || github.ref_name)
|| format('{0}/{1}', github.event.pull_request.head.repo.full_name, github.event.pull_request.head.ref)
}} --commit-hash=${{ github.event.pull_request.head.sha || github.sha }}
- name: Update status comment (Success)
if: ${{ github.event_name == 'pull_request_target' && success() }}
uses: thollander/actions-comment-pull-request@24bffb9b452ba05a4f3f77933840a6a841d1b32b # v3.0.1
with:
github-token: ${{ secrets.JF_BOT_TOKEN }}
message: |
## Cloudflare Pages deployment
| **Latest commit** | <code>${{ github.event.pull_request.head.sha || github.sha }}</code> |
|-------------------|:-:|
| **Status** | ✅ Deployed! |
| **Preview URL** | ${{ steps.cf.outputs.deployment-url != '' && steps.cf.outputs.deployment-url || 'Not available' }} |
| **Type** | 🔀 Preview |
pr-number: ${{ github.event.pull_request.number }}
comment-tag: CFPages-deployment
mode: recreate
- name: Update status comment (Failure)
if: ${{ github.event_name == 'pull_request_target' && failure() }}
uses: thollander/actions-comment-pull-request@24bffb9b452ba05a4f3f77933840a6a841d1b32b # v3.0.1
with:
github-token: ${{ secrets.JF_BOT_TOKEN }}
message: |
## Cloudflare Pages deployment
| **Latest commit** | <code>${{ github.event.pull_request.head.sha || github.sha }}</code> |
|-------------------|:-:|
| **Status** | ❌ Failure. Check workflow logs for details |
| **Preview URL** | Not available |
| **Type** | 🔀 Preview |
pr-number: ${{ github.event.pull_request.number }}
comment-tag: CFPages-deployment
mode: recreate
+148
View File
@@ -0,0 +1,148 @@
name: deploy
concurrency:
group: ${{ github.workflow }}-${{ github.event.workflow_run.head_branch || github.run_id }}
cancel-in-progress: true
on:
workflow_run:
workflows:
- build
types:
- completed
jobs:
metadata:
name: Metadata
if: ${{ github.event.workflow_run.conclusion == 'success' && github.repository == 'jellyfin/jellyfin.org' }}
runs-on: ubuntu-latest
outputs:
pr_number: ${{ steps.pr_number.outputs.pr_number }}
steps:
- name: Get Pull Request Number
id: pr_number
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
HEAD_SHA: ${{ github.event.workflow_run.head_sha }}
run: |
API_RESPONSE=$(gh pr list --repo "${GITHUB_REPOSITORY}" --search "${HEAD_SHA}" --state open --json number)
PR_NUMBER=$(echo "${API_RESPONSE}" | jq -r '.[0].number // ""')
echo "repository: ${GITHUB_REPOSITORY}"
echo "sha: ${HEAD_SHA}"
echo "response: ${API_RESPONSE}"
echo "pr: ${PR_NUMBER}"
echo "pr_number=${PR_NUMBER}" >> "${GITHUB_OUTPUT}"
deploy:
if: ${{ github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.head_branch == 'master' && github.repository == 'jellyfin/jellyfin.org' }}
name: Deploy to GitHub Pages
permissions:
actions: read
pages: write
id-token: write
concurrency: build-deploy-pages
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Configure Pages
uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0
- name: Download workflow artifact
env:
GH_TOKEN: ${{ github.token }}
run: |
gh run download "${{ github.event.workflow_run.id }}" \
--repo "${GITHUB_REPOSITORY}" \
-n "jellyfin-org__build" \
-D build
- name: Create pages artifact
run: |
tar --dereference --hard-dereference \
--directory build \
-cvf "$RUNNER_TEMP/artifact.tar" \
--exclude=.git --exclude=.github .
- name: Upload pages artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: github-pages
path: ${{ runner.temp }}/artifact.tar
retention-days: 1
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0
preview:
needs: [metadata]
if: ${{ github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.head_branch != 'master' }}
name: Deploy to Cloudflare Pages
permissions:
actions: read
runs-on: ubuntu-latest
steps:
- name: Set PR metadata
id: pr
run: |
echo "number=${{ needs.metadata.outputs.pr_number }}" >> $GITHUB_OUTPUT
echo "sha=${{ github.event.workflow_run.head_sha }}" >> $GITHUB_OUTPUT
- name: Download workflow artifact
env:
GH_TOKEN: ${{ github.token }}
run: |
gh run download "${{ github.event.workflow_run.id }}" \
--repo "${GITHUB_REPOSITORY}" \
-n "jellyfin-org__build" \
-D build
- name: Add comment
if: ${{ needs.metadata.outputs.pr_number != '' }}
uses: thollander/actions-comment-pull-request@24bffb9b452ba05a4f3f77933840a6a841d1b32b # v3.0.1
with:
github-token: ${{ secrets.JF_BOT_TOKEN }}
message: |
## Cloudflare Pages deployment
| **Latest commit** | <code>${{ steps.pr.outputs.sha }}</code> |
|-------------------|:-:|
| **Status** | 🔄 Deploying... |
| **Preview URL** | Not available |
| **Type** | 🔀 Preview |
pr-number: ${{ steps.pr.outputs.number }}
comment-tag: CFPages-deployment
mode: recreate
- name: Publish to Cloudflare
id: cf
uses: cloudflare/wrangler-action@ebbaa1584979971c8614a24965b4405ff95890e0 # v4.0.0
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: >
pages deploy build
--project-name=jellyfin-org
--branch=${{ github.event.workflow_run.head_repository.full_name }}/${{ github.event.workflow_run.head_branch }}
--commit-hash=${{ steps.pr.outputs.sha }}
- name: Update status comment
if: ${{ needs.metadata.outputs.pr_number != '' }}
uses: thollander/actions-comment-pull-request@24bffb9b452ba05a4f3f77933840a6a841d1b32b # v3.0.1
with:
github-token: ${{ secrets.JF_BOT_TOKEN }}
message: |
## Cloudflare Pages deployment
| **Latest commit** | <code>${{ steps.pr.outputs.sha }}</code> |
|-------------------|:-:|
| **Status** | ${{ job.status == 'success' && '✅ Deployed!' || '❌ Failed!' }} |
| **Preview URL** | ${{ steps.cf.outputs.deployment-url || 'Not available' }} |
| **Type** | 🔀 Preview |
pr-number: ${{ steps.pr.outputs.number }}
comment-tag: CFPages-deployment
mode: recreate
+19 -8
View File
@@ -12,13 +12,12 @@ jobs:
steps:
- name: Check out Git repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Set up Node.js
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 20
check-latest: true
node-version-file: .nvmrc
cache: npm
- name: Install Node.js dependencies
@@ -32,16 +31,15 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out Git repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Set up problem matcher
uses: xt0rted/markdownlint-problem-matcher@1a5fabfb577370cfdf5af944d418e4be3ea06f27 # v3.0.0
- name: Set up Node.js
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 20
check-latest: true
node-version-file: .nvmrc
cache: npm
- name: Install Node.js dependencies
@@ -49,3 +47,16 @@ jobs:
- name: Run markdownlint
run: npm run lint:markdown
cspell:
name: Check spelling
runs-on: ubuntu-latest
steps:
- name: Check out Git repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Run cspell
uses: streetsidesoftware/cspell-action@de2a73e963e7443969755b648a1008f77033c5b2 # v8.4.0
with:
config: ./cspell.json
+3 -4
View File
@@ -20,13 +20,12 @@ jobs:
steps:
- name: Check out Git repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Set up Node.js
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 20
check-latest: true
node-version-file: .nvmrc
cache: npm
- name: Build and start test server
+1
View File
@@ -0,0 +1 @@
26
@@ -0,0 +1,117 @@
<svg viewBox="0 0 720 330" width="100%" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Activity by month">
<defs>
<linearGradient id="sotf-activity-grad" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#AA5CC3" />
<stop offset="100%" stop-color="#00A4DC" />
</linearGradient>
</defs>
<path
d="M0.75,10.75 A10.0,10.0 0 0 1 10.75,0.75 L709.25,0.75 A10.0,10.0 0 0 1 719.25,10.75 L719.25,40.00 L0.75,40.00 Z"
fill="url(#sotf-activity-grad)"
/>
<text
x="360.0"
y="26.0"
text-anchor="middle"
font-size="17"
font-weight="700"
font-family="Plus Jakarta Sans, system-ui, -apple-system, Segoe UI, sans-serif"
fill="#ffffff"
>Activity by Month</text>
<rect x="0.75" y="0.75" width="718.5" height="328.5" rx="10" ry="10" fill="none" stroke="url(#sotf-activity-grad)" stroke-width="1.5" />
<line x1="56" y1="270.0" x2="660" y2="270.0" stroke="currentColor" stroke-width="0.5" opacity="0.15" />
<text x="48" y="274.0" text-anchor="end" font-size="10" font-family="system-ui, -apple-system, Segoe UI, sans-serif" fill="currentColor" opacity="0.7">0</text>
<line x1="56" y1="220.0" x2="660" y2="220.0" stroke="currentColor" stroke-width="0.5" opacity="0.15" />
<text x="48" y="224.0" text-anchor="end" font-size="10" font-family="system-ui, -apple-system, Segoe UI, sans-serif" fill="currentColor" opacity="0.7">150</text>
<line x1="56" y1="170.0" x2="660" y2="170.0" stroke="currentColor" stroke-width="0.5" opacity="0.15" />
<text x="48" y="174.0" text-anchor="end" font-size="10" font-family="system-ui, -apple-system, Segoe UI, sans-serif" fill="currentColor" opacity="0.7">300</text>
<line x1="56" y1="120.0" x2="660" y2="120.0" stroke="currentColor" stroke-width="0.5" opacity="0.15" />
<text x="48" y="124.0" text-anchor="end" font-size="10" font-family="system-ui, -apple-system, Segoe UI, sans-serif" fill="currentColor" opacity="0.7">450</text>
<line x1="56" y1="70.0" x2="660" y2="70.0" stroke="currentColor" stroke-width="0.5" opacity="0.15" />
<text x="48" y="74.0" text-anchor="end" font-size="10" font-family="system-ui, -apple-system, Segoe UI, sans-serif" fill="currentColor" opacity="0.7">600</text>
<text x="56.0" y="288.0" text-anchor="middle" font-size="11" font-family="system-ui, -apple-system, Segoe UI, sans-serif" fill="currentColor" opacity="0.7">May</text>
<text x="110.9" y="288.0" text-anchor="middle" font-size="11" font-family="system-ui, -apple-system, Segoe UI, sans-serif" fill="currentColor" opacity="0.7">Jun</text>
<text x="165.8" y="288.0" text-anchor="middle" font-size="11" font-family="system-ui, -apple-system, Segoe UI, sans-serif" fill="currentColor" opacity="0.7">Jul</text>
<text x="220.7" y="288.0" text-anchor="middle" font-size="11" font-family="system-ui, -apple-system, Segoe UI, sans-serif" fill="currentColor" opacity="0.7">Aug</text>
<text x="275.6" y="288.0" text-anchor="middle" font-size="11" font-family="system-ui, -apple-system, Segoe UI, sans-serif" fill="currentColor" opacity="0.7">Sep</text>
<text x="330.5" y="288.0" text-anchor="middle" font-size="11" font-family="system-ui, -apple-system, Segoe UI, sans-serif" fill="currentColor" opacity="0.7">Oct</text>
<text x="385.5" y="288.0" text-anchor="middle" font-size="11" font-family="system-ui, -apple-system, Segoe UI, sans-serif" fill="currentColor" opacity="0.7">Nov</text>
<text x="440.4" y="288.0" text-anchor="middle" font-size="11" font-family="system-ui, -apple-system, Segoe UI, sans-serif" fill="currentColor" opacity="0.7">Dec</text>
<text x="495.3" y="288.0" text-anchor="middle" font-size="11" font-family="system-ui, -apple-system, Segoe UI, sans-serif" fill="currentColor" opacity="0.7">Jan</text>
<text x="550.2" y="288.0" text-anchor="middle" font-size="11" font-family="system-ui, -apple-system, Segoe UI, sans-serif" fill="currentColor" opacity="0.7">Feb</text>
<text x="605.1" y="288.0" text-anchor="middle" font-size="11" font-family="system-ui, -apple-system, Segoe UI, sans-serif" fill="currentColor" opacity="0.7">Mar</text>
<text x="660.0" y="288.0" text-anchor="middle" font-size="11" font-family="system-ui, -apple-system, Segoe UI, sans-serif" fill="currentColor" opacity="0.7">Apr</text>
<polyline
points="56.0,155.7 110.9,143.7 165.8,184.7 220.7,172.7 275.6,155.3 330.5,125.3 385.5,179.7 440.4,131.0 495.3,176.7 550.2,209.3 605.1,148.7 660.0,157.0"
fill="none"
stroke="#22c55e"
stroke-width="2"
stroke-linejoin="round"
stroke-linecap="round"
/>
<circle cx="56.0" cy="155.7" r="3" fill="#22c55e"><title>May: 343 prs merged</title></circle>
<circle cx="110.9" cy="143.7" r="3" fill="#22c55e"><title>Jun: 379 prs merged</title></circle>
<circle cx="165.8" cy="184.7" r="3" fill="#22c55e"><title>Jul: 256 prs merged</title></circle>
<circle cx="220.7" cy="172.7" r="3" fill="#22c55e"><title>Aug: 292 prs merged</title></circle>
<circle cx="275.6" cy="155.3" r="3" fill="#22c55e"><title>Sep: 344 prs merged</title></circle>
<circle cx="330.5" cy="125.3" r="3" fill="#22c55e"><title>Oct: 434 prs merged</title></circle>
<circle cx="385.5" cy="179.7" r="3" fill="#22c55e"><title>Nov: 271 prs merged</title></circle>
<circle cx="440.4" cy="131.0" r="3" fill="#22c55e"><title>Dec: 417 prs merged</title></circle>
<circle cx="495.3" cy="176.7" r="3" fill="#22c55e"><title>Jan: 280 prs merged</title></circle>
<circle cx="550.2" cy="209.3" r="3" fill="#22c55e"><title>Feb: 182 prs merged</title></circle>
<circle cx="605.1" cy="148.7" r="3" fill="#22c55e"><title>Mar: 364 prs merged</title></circle>
<circle cx="660.0" cy="157.0" r="3" fill="#22c55e"><title>Apr: 339 prs merged</title></circle>
<polyline
points="56.0,129.7 110.9,123.0 165.8,171.0 220.7,159.7 275.6,137.3 330.5,102.0 385.5,161.3 440.4,105.3 495.3,148.0 550.2,190.7 605.1,110.7 660.0,107.0"
fill="none"
stroke="#ef4444"
stroke-width="2"
stroke-linejoin="round"
stroke-linecap="round"
/>
<circle cx="56.0" cy="129.7" r="3" fill="#ef4444"><title>May: 421 issues closed</title></circle>
<circle cx="110.9" cy="123.0" r="3" fill="#ef4444"><title>Jun: 441 issues closed</title></circle>
<circle cx="165.8" cy="171.0" r="3" fill="#ef4444"><title>Jul: 297 issues closed</title></circle>
<circle cx="220.7" cy="159.7" r="3" fill="#ef4444"><title>Aug: 331 issues closed</title></circle>
<circle cx="275.6" cy="137.3" r="3" fill="#ef4444"><title>Sep: 398 issues closed</title></circle>
<circle cx="330.5" cy="102.0" r="3" fill="#ef4444"><title>Oct: 504 issues closed</title></circle>
<circle cx="385.5" cy="161.3" r="3" fill="#ef4444"><title>Nov: 326 issues closed</title></circle>
<circle cx="440.4" cy="105.3" r="3" fill="#ef4444"><title>Dec: 494 issues closed</title></circle>
<circle cx="495.3" cy="148.0" r="3" fill="#ef4444"><title>Jan: 366 issues closed</title></circle>
<circle cx="550.2" cy="190.7" r="3" fill="#ef4444"><title>Feb: 238 issues closed</title></circle>
<circle cx="605.1" cy="110.7" r="3" fill="#ef4444"><title>Mar: 478 issues closed</title></circle>
<circle cx="660.0" cy="107.0" r="3" fill="#ef4444"><title>Apr: 489 issues closed</title></circle>
<polyline
points="56.0,253.3 110.9,249.7 165.8,254.0 220.7,254.7 275.6,253.3 330.5,249.0 385.5,250.3 440.4,245.0 495.3,249.3 550.2,254.0 605.1,245.7 660.0,246.0"
fill="none"
stroke="#eab308"
stroke-width="2"
stroke-linejoin="round"
stroke-linecap="round"
/>
<circle cx="56.0" cy="253.3" r="3" fill="#eab308"><title>May: 50 contributors</title></circle>
<circle cx="110.9" cy="249.7" r="3" fill="#eab308"><title>Jun: 61 contributors</title></circle>
<circle cx="165.8" cy="254.0" r="3" fill="#eab308"><title>Jul: 48 contributors</title></circle>
<circle cx="220.7" cy="254.7" r="3" fill="#eab308"><title>Aug: 46 contributors</title></circle>
<circle cx="275.6" cy="253.3" r="3" fill="#eab308"><title>Sep: 50 contributors</title></circle>
<circle cx="330.5" cy="249.0" r="3" fill="#eab308"><title>Oct: 63 contributors</title></circle>
<circle cx="385.5" cy="250.3" r="3" fill="#eab308"><title>Nov: 59 contributors</title></circle>
<circle cx="440.4" cy="245.0" r="3" fill="#eab308"><title>Dec: 75 contributors</title></circle>
<circle cx="495.3" cy="249.3" r="3" fill="#eab308"><title>Jan: 62 contributors</title></circle>
<circle cx="550.2" cy="254.0" r="3" fill="#eab308"><title>Feb: 48 contributors</title></circle>
<circle cx="605.1" cy="245.7" r="3" fill="#eab308"><title>Mar: 73 contributors</title></circle>
<circle cx="660.0" cy="246.0" r="3" fill="#eab308"><title>Apr: 72 contributors</title></circle>
<circle cx="200" cy="316" r="4" fill="#22c55e" />
<text x="210" y="320" font-size="11" font-family="system-ui, -apple-system, Segoe UI, sans-serif" fill="currentColor" opacity="0.85">PRs Merged</text>
<circle cx="340" cy="316" r="4" fill="#ef4444" />
<text x="350" y="320" font-size="11" font-family="system-ui, -apple-system, Segoe UI, sans-serif" fill="currentColor" opacity="0.85">Issues Closed</text>
<circle cx="480" cy="316" r="4" fill="#eab308" />
<text x="490" y="320" font-size="11" font-family="system-ui, -apple-system, Segoe UI, sans-serif" fill="currentColor" opacity="0.85">Contributors</text>
</svg>

After

Width:  |  Height:  |  Size: 9.1 KiB

+265
View File
@@ -0,0 +1,265 @@
---
title: State of the Fin 2026-05-24
authors:
- jellyfin
slug: state-of-the-fin-2026-05-24
tags: [state-of-the-fin]
---
import ActivityChart from './activity-by-month.svg';
Welcome to the second edition of State of the Fin! This update will be slightly different to the previous one as we don't have as many large updates to announce (yet)! Still, we want to keep you informed on what is happening and what the Jellyfin development team are working on. Please enjoy, and contribute through our [standard channels](/contact) if you have questions or comments.
{/* truncate */}
## Project Updates
#### Versioning
As mentioned in the last [State of the Fin](/blog/2026/01-06-state-of-the-fin/index.mdx#versioning), we're dropping the major version "10" from our naming scheme. With 10.11.x being the final release branch to use it, the next major release will move directly to 12.0. The primary reason for this is to reduce confusion about what a "major" version is and eliminate the redundancy of a never-changing `10`. version prefix.
#### LLM/"AI" Policy
As with pretty much every open source project, we have been inundated with AI-authored pull requests of varying quality. This has vastly increased the amount of work the team has on their plate. To that end, an LLM/AI Policy has been created to try and help set standards. The tl;dr is **AI use isn't completely forbidden in pull requests/code submissions, however you must understand HOW it does what it does, and any posts to a pull request/issue should be written by the user. You cannot function as a go-between between your AI and our questions/comments, just copy-pasting whatever the AI tells you.** For more information, please read the [LLM/"AI" developmental policy](/docs/general/contributing/llm-policies) we have published.
The Jellyfin Team is made up of a lot of different people, and everyone has different levels of acceptance of/interest in code that an AI agent has contributed to. This policy has been made to try and help find a path that everyone can at least appreciate, even if they don't fully agree.
#### Burnout / Remember the Person
Jellyfin has been growing quickly as the landscape around us matures and changes. This is both a blessing and a curse. It is great that Jellyfin is so popular and loved by so many, however the increased support requests, combined with the AI code submissions, have led to burnout at various levels of the development and admin team. Abuse from users when something isn't working or a change isn't accepted only increases the loss of motivation. This has already led to delays in client and server improvements.
Please remember Jellyfin is open source and is written by volunteers. There are real people doing the work, and they're doing this for the love of the project. Yelling at them/insulting them will not make anything happen faster, and is actually more likely to delay fixes or improvements.
If you'd like to get involved in helping fellow users, hang out in the [standard Matrix/Discord channels](/contact), or look at the [forums](https://forum.jellyfin.org/)/[subreddit](https://reddit.com/r/jellyfin) and volunteer answers when you think the question is something you know. Straight AI searching and copy-paste answering aren't good responses and are explicitly banned by the aforementioned LLM policy, but if it's something you have dealt with, please contribute! The more people who help answer the easy questions, the more we can allow the devs to work on the hard stuff.
And of course, if you want to contribute code, we welcome it! Bug fixes are always welcome as-is; but features require a bit more work and a policy that we are still in the process of defining. But if you want to work on a feature, the short answer is: please ask us before you start implementing it and work with the team on a full design/scope discussion to help ensure your work will be accepted!
## Development Updates
<ActivityChart />
#### What's New
We've continued pushing bug and [security](https://github.com/jellyfin/jellyfin/security/advisories) fixes to the stable release. Following the 10.11.10 release, development attention has largely shifted toward finalizing 12.0 ahead of the upcoming release candidate phase. A few items still need to be addressed before we can ship RC1: [Jellyfin 12.0](https://github.com/orgs/jellyfin/projects/73)
The [Performance PR](https://github.com/jellyfin/jellyfin/pull/16062) which forms the foundation for much of the work in 12.0, has been merged into master and is now part of the weekly unstable releases. These are published every Monday, though we may push additional out-of-band builds for a while to support testing. Unstable builds can be accessed via Docker using the "unstable" tag or by selecting the unstable tab on our downloads page.
This PR addresses a number of slow queries in 10.11.x, particularly for folder-based libraries like home videos & photos, and books. Other areas have also seen improvements, including collections, music libraries, playlists, and homepage load times. For more details, see the PR description.
12.0 also includes a fix for EPG issues with the Schedules Direct API, as well as a fix for errors when restructuring media libraries. A long-requested feature, support for multiple versions of episodes in a series library, has also been added. While users may notice some incidental improvements in scanner performance as a result of other changes, scanner optimization itself was not a primary focus of this release. More substantial work in that area is planned for 13.0, which is currently in the early [planning phase](https://github.com/jellyfin/jellyfin-meta/discussions/125).
#### Testing
Before testing the unstable 12.0 build, please note the following:
Unstable builds are not guaranteed to work from one build to another. These builds should only be used for testing or evaluating new features, and running them as a daily driver is at your own risk.
If upgrading from an earlier version, a full backup of the data directory is strongly recommended, as this release includes database changes that prevent rolling back without a full restore.
Installed repository plugins (anything not built-in) should also be removed before migrating. Plugins will likely need time to adapt to the new database changes, so re-adding them afterward is the safest approach for testing.
Official plugins compatible with Jellyfin are available through the unstable plugin repository. To test plugins for 12.0:
- Go to Dashboard -> Plugins -> Manage Repositories
- Update the Plugin Repository URL to: https://repo.jellyfin.org/files/plugin-unstable/manifest.json
After migrating:
- Perform a full library scan to restore alternative versions
- Run the "Optimize database" scheduled task
If you run into issues, please prefix bug reports with "[12.0]".
#### Client Development Changes
As mentioned [before](/blog/2025/10-19-jellyfin-release-10.11.0/index.mdx#client-development-changes), the API will no longer allow deprecated authorization mechanisms by default, so clients and tooling that haven't already migrated will need to update. Any new API changes or breaking modifications not already in progress will now be deferred to 13.0, allowing client developers to begin targeting a stable API surface ahead of release.
That said, we've temporarily reverted the [default enforcement](https://github.com/jellyfin/jellyfin/pull/16754) during the testing phase, since some of our official clients are still in the process of completing the transition.
## Client Corner
### [Jellyfin for Android](https://github.com/jellyfin/jellyfin-android)
#### What's New
The mobile Android app stopped working after the recent 10.11.7 server update and was quickly resolved in 10.11.8. To keep the same problem from recurring, the app itself was also patched in the 2.6.4 release.
#### Notable Changes
- New patches in the 2.6.4 release to make sure a similar problem doesn't happen again.
- The 2.6.4 build is not available on the Google Play store for technical reasons.
#### What's Next
Work is ongoing for the upcoming 2.7.0 update. Recently we've finished the re-implementation of Android Auto support which was the major blocker for the next release. We'll likely start a beta cycle to collect feedback in the coming weeks/months. This version of the app will be compatible with Jellyfin 10.10 and newer.
*- [Niels van Velzen](https://github.com/nielsvanvelzen)*
### [Jellyfin for Android TV](https://github.com/jellyfin/jellyfin-androidtv)
#### What's New
Three updates to the app went live since our last State of the Fin, version 0.19.7 and 0.19.8 both fix numerous bugs. Most notably is a bug where our progress bar would be incorrect for some users. That's now fixed! In version 0.19.9 we made some improvements to the home screen to make it load faster and solved a long-term issue with the screensaver not working after playing a video.
#### What's Next
Work is still progressing on the next big Android TV release.
Version 0.20 will have a completely revamped look for the settings and also expands them to allow more customization and tweaking playback options. Work also continues on the new video player, with various features also made available to the current one, like support for SubStation Alpha subtitles and better handling of external apps for video playback.
This version of the app will require Jellyfin server 10.11 or newer. Due to community feedback, we have postponed the release until Jellyfin 12.0 is released. However, the beta versions of the app will likely start earlier and the app already notifies people about updating their server to 10.11.
*- [Niels van Velzen](https://github.com/nielsvanvelzen)*
### [Jellyfin for Desktop](https://github.com/jellyfin/jellyfin-desktop)
#### What's New
Jellyfin Desktop is being completely rewritten to address several performance, feature, and maintainability issues. Qt and its Chromium-based QtWebEngine have been replaced with Chromium Embedded Framework (CEF) to drastically improve responsiveness. The removal of Qt means we are no longer bound to a dependency that has historically been problematic when maintaining this project (Qt5->6, Qt WebEngine memory leaks). As for the audio/video side of things, we've switched from the legacy libmpv pipeline to the same modern pipeline that standalone mpv uses. This enables both better GPU acceleration (`vo=gpu-next`) and native HDR playback (Wayland/macOS/Windows). CEF and mpv are integrated via platform-native mechanisms that seamlessly overlay CEF on top of the video playback performance of standalone mpv. Long term, this should allow us to combine the functionality of Jellyfin MPV Shim into the Jellyfin Desktop codebase.
Although it's not yet ready for a stable v3.0.0 release, development builds are available in the [project's GitHub](https://github.com/jellyfin/jellyfin-desktop/). I actively welcome any bug reports or feature requests as they are incredibly helpful in prioritizing a sustainable, long-term codebase. To all early testers: thank you!
#### Notable Changes
- Completely rewritten without Qt/QtWebEngine
- Uses CEF as the browser engine
- Reworked audio/video pipeline to use the same as standalone mpv
- Supports mpv.conf and mpv plugins
- Linux AppImage support added
- Windows ARM support added
#### Known Issues
- Some features found in v1.x and v2.x are missing
#### What's Next
- Stabilize architecture to allow for better programmatic testing
- Formal v3.0.0 pre-release
*- [Andrew Rabert](https://github.com/andrewrabert)*
### [Jellyfin for Kodi](https://github.com/jellyfin/jellyfin-kodi)
#### What's New
A couple of long-requested features have been completed in this period along with bug fixes and general cleanup.
#### Notable Changes
- Media Segments are now supported.
- Quick Connect support has been merged and will be included in a future release.
*- [MCarlton00](https://github.com/mcarlton00)*
### [Jellyfin for Roku](https://github.com/jellyfin/jellyfin-roku)
#### Latest Release: 3.1.9
#### Minimum Server Version: 10.9.0
#### Highlights
- New setting allowing you to change the poster orientation in libraries
- New settings allowing you to change playback speed
- Choose between 1 or 5 displayed trickplay images
- OSD seekbar is now fully functional
- Custom subtitles now support font color tags
- Subtitle timing offset now available for custom subtitles
- Many more direct play profiles added
- Oh so many bug fixes
- And so much more!
#### What's Next
- More custom subtitle enhancements (bold & italic?!?! 😱 )
- Default subtitle selection improvements
- Default audio track selection improvements
*- [1hitsong](https://github.com/1hitsong)*
### [Jellyfin for Tizen](https://github.com/jellyfin/jellyfin-tizen)
#### What's New
The [Tizen Jellyfin client](https://github.com/jellyfin/jellyfin-tizen) for Tizen 6 and newer has been released to the Samsung Tizen Store! Tizen 5 and earlier should still be able to side-load the client.
*- [Eric Stacey](https://github.com/ejstacey)*
### [Jellyfin for Xbox](https://github.com/jellyfin/jellyfin-xbox)
#### What's New
Since the last State of the Fin, Jellyfin for Xbox has seen several new PRs for various fixes and improvements. We also checked off a major item from the previous State of the Fin todo list: Jellyfin for Xbox now supports translations!
#### Notable Changes
- **UI Refresh**: Various UX fixes and improvements throughout the app interface.
- **Log File Upload Dialog**: A new dialog allows uploading any of the last 6 log files directly from within the app.
- **Translation Support**: Jellyfin for Xbox now supports localization!
<img src="https://translate.jellyfin.org/widget/jellyfin-for-xbox/multi-auto.svg" alt="Translation support" style={{maxWidth: '300px', width: '100%'}} />
#### What's Next
A new v0.9.5 release incorporating these changes is coming soon!
*- [Jean-Pierre Bachmann](https://github.com/JPVenson)*
## Jellyfin Labs
### [Swiftfin](https://github.com/jellyfin/Swiftfin)
#### What's New
Swiftfin has had a lot of recent development in preparation for 1.5 and our next tvOS release. A lot of our recent work has been focused on utilizing new SwiftUI improvements to better unify work between iOS and tvOS. There is a lot of effort involved in this but this should help improve our release cadence moving forward.
#### Notable Changes
- Many iOS player bug fixes and additional supplement information & customization.
- Structural changes to better unify iOS and tvOS development moving forward.
- Lots of work towards our next [tvOS release](https://github.com/jellyfin/Swiftfin/discussions/1294) including the resolution of some [longstanding and high profile issues](https://github.com/jellyfin/Swiftfin/issues/776)!
#### Known Issues
- In the final version of Jellyfin 12.0, Swiftfin tvOS will not be able to authenticate without [enabling legacy authentication](https://gist.github.com/nielsvanvelzen/ea047d9028f676185832e51ffaf12a6f#disabling-deprecated-authorization-methods). This is resolved for iOS/iPadOS and will be resolved in the next tvOS release. _It is **our goal** to have a new tvOS release before 12.0 is out of testing._
#### What's Next
We are working hard on our next release! If you are interested in helping out, please see our [Help Wanted](https://github.com/jellyfin/Swiftfin/discussions/1503) post for details on getting started!
*- [Joe Kribs](https://github.com/JPKribs)*
### Jellyfin for Titan OS & Vega OS
Work has started on two new Jellyfin clients!
Currently in the prototype phase is a Jellyfin client for the new **Vega OS** platform from Amazon. This is the operating system used on the newer models of Fire TV Sticks released since 2025. We've seen a lot of requests for this as people buy the devices thinking they can use our Android TV app and end up not finding Jellyfin.
Further into development is our client for **Titan OS**. This smart TV platform is mainly found on Philips televisions. We're currently testing this client and hopefully have some news to share soon!
*- [Niels van Velzen](https://github.com/nielsvanvelzen)*
## [Documentation](https://github.com/jellyfin/jellyfin.org)
#### What's New
Documentation is always a work in progress but over this period Jellyfin's documentation has seen some notable changes:
- Improved CI to catch common issues and spelling errors
- A new feature proposal guideline
- Fish shell support added to the installer commands
- Cleanup of reverse proxy documentation
- The LLM policy made its way into the docs
#### Moving Forward
New contributors have been assisting, which has been a tremendous help! Thank you to everyone who has pitched in so far. If you are interested in getting involved, please feel free to create a PR.
*- [BotBlake](https://github.com/BotBlake)*
## Closing Thoughts
While this post isn't full of new announcements, it's worth posting so you know people are still working on things in the background. Jellyfin was originally forked from Emby, however the projects have different goals and directions. For Jellyfin, this includes some very deep rewrites of core code, which takes a lot of time and effort. It is necessary to help the codebase mature for the future of the project. We hope with the extra details given in this blog, which are public but generally not broadcasted, you can appreciate the scope and size of the Jellyfin work, and the people behind it. Thank you for using and supporting Jellyfin!
\- [Eric Stacey](https://github.com/ejstacey)
Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 311 KiB

+152
View File
@@ -0,0 +1,152 @@
---
title: Jellyfin for Android 2.7
authors:
- nielsvanvelzen
slug: android-v2.7
tags: [release, android]
---
We're excited to announce the release of **Jellyfin for Android 2.7**! This release introduces one of the largest updates to the app so
far, with a completely redesigned downloads experience, revamped Android Auto support, major playback improvements, and many bug fixes and
quality-of-life enhancements.
{/* truncate */}
Thank you to everyone who contributed code, tested beta releases, reported bugs, and helped improve the app throughout this release cycle.
import androidDownloadDemoPng from './android-download-demo.png';
<div className="row">
<div className="col col--8">
## Redesigned downloads
The download functionality of the app was completely redesigned, adding many new features and making your downloads fully manageable in-app.
It is now possible to see all your downloads inside the app and play them. Video files are played with the app's own video player, other
media types will open in a compatible external app. The first time you download something, the app will ask you to choose a folder to store
all your downloads in. Unfortunately, your existing downloads cannot be migrated.
And this is only the start! We're planning to add better filtering and browsing of your downloads and improved offline support where your
watch state will be synchronized with the server once you're back online.
</div>
<div className="col col--4 margin-top--md">
<img
src={androidDownloadDemoPng}
alt="Screenshot of the redesigned downloads screen"
style={{ width: '100%', maxWidth: '400px' }}
/>
</div>
</div>
## Android Auto support
![Photo of the Android Auto integration](./android-auto-demo.jpg)
Android Auto support has long been one of the Jellyfin app's most popular features, making it easy to enjoy your music while on the go. This
release brings a major overhaul to the Android Auto support. You can now browse your large music libraries without being limited to just 250
results. We've also improved the search and, perhaps most excitingly, added support for audiobooks!
To achieve these changes the Android Auto integration was completely rewritten from the ground up. This makes it easier to maintain and
expand with more features in future releases.
## Better playback
Hidden in the app's settings is an option to change the app's video player implementation. Until now, this has always been set to the "web"
player. This was mainly because we weren't confident yet that our "native" video player was ready for everyone. Starting with version 2.7,
that's changing. The native video player is now the default, allowing for more efficient playback and reducing the need for transcoding.
The native video player also received several improvements. It now supports TrickPlay images while scrubbing, includes a gesture to quickly
seek forward or backward in your video, supports media segments for skipping, and has a better fallback mechanism when a video fails to
play.
## Android improvements
Version 2.7 now targets **Android 16 (SDK 36)** and supports Android's per-app language preferences, allowing Jellyfin to use a different
language than the rest of your device. We've also ensured the app is compatible with the recently released Android 17. Other improvements
include better codec detection for direct playback and enhancements to the "now playing" notification.
## Android 5 and below
**This release will be the last to support Android 5 and Android 5.1** due to updated vendor requirements. Based on our limited statistics,
this affects fewer than 1% of our users. You'll still be able to use Jellyfin, but won't be able to receive future app updates. We recommend
upgrading your device to receive future app updates.
## Made possible by you
Jellyfin is completely developed by volunteers, and couldn't be made without their great skills and dedication. Consider donating if you
appreciate their work. A big shout-out to all contributors that made this release possible:
**Jellyfin Team**
- [@nielsvanvelzen](https://github.com/nielsvanvelzen) - Donate via [Buy Me a Coffee](https://buymeacoffee.com/nielsvanvelzen) or
[GitHub sponsors](https://github.com/sponsors/nielsvanvelzen)
- [@Maxr1998](https://github.com/Maxr1998) - Donate via [GitHub sponsors](https://github.com/sponsors/Maxr1998)
- [@BotBlake](https://github.com/BotBlake) - Donate via [GitHub sponsors](https://github.com/sponsors/BotBlake)
- [@thedreaddpirate](https://github.com/thedreaddpirate) - Donate via [GitHub sponsors](https://github.com/sponsors/thedreaddpirate)
**Other contributors**
<div style={{ columns: 2 }}>
{/* cspell:disable */}
- [@3flex](https://github.com/3flex)
- [@CeruleanRed](https://github.com/CeruleanRed)
- [@7ritn](https://github.com/7ritn)
- [@comp500](https://github.com/comp500)
- [@Ank1996](https://github.com/Ank1996)
- [@Tukajo](https://github.com/Tukajo)
- [@lfranke42](https://github.com/lfranke42)
- [@jakobkukla](https://github.com/jakobkukla)
- [@s12f](https://github.com/s12f)
- [@miikaforma](https://github.com/miikaforma)
- [@cameocoder](https://github.com/cameocoder)
- [@gert7](https://github.com/gert7)
- [@RonDen\-DidIt](https://github.com/RonDen-DidIt)
- [@TheMrMilchmann](https://github.com/TheMrMilchmann)
- [@rodis120](https://github.com/rodis120)
- [@jagadam97](https://github.com/jagadam97)
- [@VTRunner](https://github.com/VTRunner)
- [@SJJ\-dot](https://github.com/SJJ-dot)
- [@DevGitPit](https://github.com/DevGitPit)
- [@kfarnung](https://github.com/kfarnung)
- [@GeiserX](https://github.com/GeiserX)
- [@tal\-sarid](https://github.com/tal-sarid)
- [@stumpylog](https://github.com/stumpylog)
- [@mherceg](https://github.com/mherceg)
- [@jim\-daf](https://github.com/jim-daf)
- [@jordanmichaelrushing](https://github.com/jordanmichaelrushing)
- [@JDStriker456](https://github.com/JDStriker456)
{/* cspell:enable */}
</div>
<br />
And finally a big thank you to everyone who contributed translations, reported bugs, provided feedback and participated in beta testing!
### Helping out
If you have experience with Android development or with Kotlin and are interested in contributing yourself, feel free to dive into the
[source code](https://github.com/jellyfin/jellyfin-android) and open a pull request. Alternatively, you can help with translating the app
into your own language on our [Weblate](https://translate.jellyfin.org/engage/jellyfin-android/) instance.
## Downloads
Update your app now to check out all these changes! The app stores will auto-update your Jellyfin app if you're already using the app. For
new users, you can find the app on the app store of your platform.
<a className='margin-right--md' href='https://play.google.com/store/apps/details?id=org.jellyfin.mobile'>
<img width='153' alt='Jellyfin on Google Play' src='/images/store-icons/google-play.png' />
</a>
<a href='https://f-droid.org/en/packages/org.jellyfin.mobile/'>
<img width='153' alt='Jellyfin on F-Droid' src='/images/store-icons/fdroid.png' />
</a>
Direct downloads are available at [repo.jellyfin.org](https://repo.jellyfin.org/releases/client/android/) or in the
[GitHub release](https://github.com/jellyfin/jellyfin-android/releases/latest).
You can also join our [beta program on Google Play](https://play.google.com/apps/testing/org.jellyfin.mobile) and help test new versions
before they're released to the public. [Read more](../../2021/07-24-android-betas.mdx) about our beta program.
+6
View File
@@ -1,3 +1,9 @@
jellyfin:
name: Jellyfin Team
title: Jellyfin Team
url: https://jellyfin.org/
image_url: https://avatars.githubusercontent.com/u/45698031?s=200&v=4
1hitsong:
name: 1hitsong
title: Roku Team
+28
View File
@@ -0,0 +1,28 @@
{
"$schema": "https://raw.githubusercontent.com/streetsidesoftware/cspell/main/cspell.schema.json",
"version": "0.2",
"language": "en, en-US, en-GB",
"allowCompoundWords": true,
"files": ["**/*.md", "**/*.mdx", "**/*.tsx"],
"dictionaryDefinitions": [
{
"name": "project-words",
"path": "./project-words.txt",
"addWords": true
}
],
"dictionaries": ["project-words"],
"ignorePaths": [
"node_modules",
"/project-words.txt",
"/src/components/common/PlatformIcon.tsx",
"/blog/2019/*",
"/blog/2020/*",
"/blog/2021/*",
"/blog/2022/*",
"/blog/2023/*",
"/blog/2024/*",
"/blog/2025/*"
]
}
-3
View File
@@ -26,9 +26,6 @@ The core team consists of those with merge permissions on the main Jellyfin repo
| Person | Contact | Role(s) |
|---|---|---|
| Joshua Boniface | [GitHub](https://github.com/joshuaboniface) [Matrix](https://matrix.to/#/@joshuaboniface:bonifacelabs.ca) [Email](mailto:joshua@boniface.me) | **Project Leader**, Packaging, Releases, Finance, Infrastructure |
| Anthony Lavado | [GitHub](https://github.com/anthonylavado) | Social Media, Outreach, Finance |
| Andrew Rabert | [GitHub](https://github.com/nvllsvm) | Finance |
| Bond-009 | [GitHub](https://github.com/Bond-009) | Server |
| Claus Vium | [GitHub](https://github.com/cvium) | Server |
| Bill Thornton | [GitHub](https://github.com/thornbill) | Web |
@@ -31,7 +31,7 @@ To take a new Backup, enter the Jellyfin Dashboard, open the `Backups` tab and c
- Database. Always enabled. Will contain all data from the jellyfin.db or used database provider.
- Metadata. The contents of the metadata folder and depending on your selected options may contain metadata images.
- Subtitles. All extracted subtitles including downloaded ones.
- Trickplay. All trickplay data that is stored not alongside media.
- Trickplay. All Trickplay data that is stored not alongside media.
The Backup system will check for at least 5GB of free space in the backup folder where backups a written to. However this can easily not be enough if you also backup Subtitles and Trickplay so ensure you have enough free space there.
The Backup folder is located within your Jellyfin data directory, by default:
@@ -26,7 +26,7 @@ Some component recommendations do not change regardless of the hardware configur
Different vendors have different hardware encoder implementations and produce different results. Usually, newer generations within the same vendor will provide better results. The following is a quick comparison on the quality between vendors on modern products.
Apple ≥ Intel ≥ NVIDIA >>> AMD<sup>\*</sup>
NVIDIA (RTX 50) ≥ Intel (Arc-B) ≥ Apple ≥ Intel ≥ NVIDIA ≥ AMD ≥ AMD H.264 (RX 9000) >>> AMD H.264<sup>\*</sup>
<sup>\*</sup> This only represents the default Jellyfin settings. The quality may be different depending on your exact configuration.
@@ -58,7 +58,7 @@ Intel Drivers are much easier to install on Linux, with many distributions inclu
:::caution
Intel ARC B series cards require ReBar to be enabled. This means you must use it on a platform with Intel 10th gen, AMD Ryzen 3000 series or newer.
Intel ARC B-series cards require ReBar to be enabled. This means you must use it on a platform with Intel 10th gen, AMD Ryzen 3000 series or newer. Intel ARC A-series cards do not require ReBar to function, however, ReBar should be enabled for optimal performance.
:::
@@ -85,6 +85,7 @@ These hardware platforms might lead to a poor Jellyfin experience. Please be car
- Most Single Board Computers (SBC): Most SBCs (including the Raspberry Pi, **especially the Raspberry Pi 5**) are too slow to provide an acceptable Jellyfin experience as they often lack proper support for hardware acceleration. If you really want to run Jellyfin on an SBC, you may wish to consider models based on the following platforms: Rockchip RK3588 / RK3588S, Intel Core, Intel 12th gen N series
- AMD Graphics: AMD Graphics have poor encoder quality and poor driver support. **This applies even on Linux**.
- Low-end GPUs: Certain low-end GPUs (e.g. GT1030, RX6400) are not capable of hardware encoding. These models cannot be used for hardware acceleration for a Jellyfin Server.
- Very old X86 CPUs: Starting with Jellyfin 10.11, X86 CPUs that support the SSE4.1 instruction set is a requirement. For Intel, Penryn (Q4 2007) and newer support SSE4.1. For AMD, Bulldozer (Q4 2011) and newer support SSE4.1.
## Detailed Guide
@@ -130,18 +131,26 @@ It is recommended to add more memory when using Windows 11 due to the OS being h
### Graphics Cards (GPUs)
:::note
The quality of transcoded video is highly dependent on the target codecs used by your client and your GPU architecture. Make sure you have verified them so you can choose the GPU best suited for your use case.
:::
With modern systems, the media engines are usually located on the GPUs. Therefore, the available hardware acceleration options are determined by the choice of GPU.
Encoder Quality: Apple ≥ Intel ≥ NVIDIA >>> AMD<sup>\*</sup>
Encoder Quality: NVIDIA (RTX 50) ≥ Intel (Arc-B) ≥ Apple ≥ Intel ≥ NVIDIA ≥ AMD ≥ AMD H.264 (RX 9000) >>> AMD H.264<sup>\*</sup>
<sup>\*</sup> This only represents the default Jellyfin settings. The quality may be different depending on your exact configuration.
NVIDIA [Blackwell (RTX 50) NVENC](https://en.wikipedia.org/wiki/NVENC#Versions) represents the state of the art in hardware encoder quality. It introduces more optimized encoding tools, allowing it to deliver significant quality gains over its predecessor, Ada (RTX 40), and even Intel Arc Battlemage. The most visible difference is that Intel's encoder is more likely to produce blocky artifacts when processing dark details.
Intel is always recommended on non-Apple hardware for the following reasons:
- Intel provides a good quality encoder, slightly better than NVIDIA and significantly better than AMD.
- Intel drivers and the compute environment is much easier to setup than both NVIDIA and AMD
- Intel provides a good quality encoder, slightly better than pre-Blackwell NVIDIA and significantly better than AMD H.264.
- Intel drivers and the compute environment is much easier to setup than NVIDIA.
AMD is not recommended due to poor quality H.264 and H.265 (HEVC) output, as well as being hard to set up the compute environment. While AMD has significantly improved AV1 encoder quality, you are still more likely to transcode to H.264 or H.265 than to AV1 due to the hardware capabilities of the average Jellyfin client.
AMD is the least preferred choice due to its sub-par H.264 encoders prior to RDNA4 (RX 9000). While its H.265 (HEVC) and AV1 encoders offer noticeable improvements, they still lag behind Intel and NVIDIA. Since the average Jellyfin client relies heavily on H.264 hardware decoding, you will inevitably transcode to H.264 most of the time, making AMD's weakness a major bottleneck.
A list of common codecs can be found in the [codec support documentation](/docs/general/clients/codec-support/).
@@ -175,7 +184,10 @@ Certain low-end cards (e.g. GT 1030) do not have encoding hardware. Please be ca
#### AMD Graphics
AMD graphics is not recommended for Jellyfin, this information is solely provided for reference. Further reading on AMD VCE supported codecs: [https://en.wikipedia.org/wiki/Video_Coding_Engine](https://en.wikipedia.org/wiki/Video_Coding_Engine).
AMD graphics are the least preferred choice for Jellyfin, this information is solely provided for reference. Further reading on AMD VCN & VCE supported codecs:
- [https://en.wikipedia.org/wiki/Video_Core_Next](https://en.wikipedia.org/wiki/Video_Core_Next)
- [https://en.wikipedia.org/wiki/Video_Coding_Engine](https://en.wikipedia.org/wiki/Video_Coding_Engine)
Certain low-end cards (e.g., RX 6400, RX 6500) do not have encoding hardware. Please be careful when choosing a GPU.
-6
View File
@@ -9,12 +9,6 @@ This page covers migrations of Jellyfin as well as migrations to Jellyfin.
Jellyfins internal databases cannot be copied or adjusted easily. Depending on your case there may be ways to work around this, for example by just migrating parts of the data, or because it's possible maintain the same file paths.
If that's not an option for you, there is also a script available to migrate the entire database without data loss, but it's not a turn-key solution.
## Full Database Migration
[Jellyfin Migrator](https://github.com/MMMZZZZ/Jellyfin-Migrator) is a third-party script that can migrate your entire installation from Windows to Linux or Linux Docker. It can also do other migrations, like a reorganization of your media files. All statistics, settings and metadata are preserved.
## Watched Status Migration
There are third-party scripts available that will use the API to copy watched status and users from one instance to another.
+28 -8
View File
@@ -3,15 +3,13 @@ uid: server-storage
title: Storage
---
## Storage
Jellyfin is designed to directly read media from the filesystem. A network storage device that is using samba or NFS must be directly mounted to the OS. The Jellyfin database should also be stored locally and not on a network storage device.
:::caution
There are [scheduled maintenance tasks](/docs/general/server/tasks) which remove items from your library if triggered while your media storage is unavailable.
:::
### NFS
## NFS
In case you encounter performance issues where files take a long time to start playing while using NFSv3, you might be running in an issue with .NET locking without NFSv3 having locking enabled.
@@ -22,18 +20,40 @@ To solve this, you have the following options:
- Enable the lock service.
- Use NFSv4 which has built-in lock support.
## Docker or VMs
## Docker and VMs
For storage, a moderate size library database can grow anywhere from 10 to 100 GB. The [transcoding](/docs/general/post-install/transcoding) folder needs roughly the same size as the original media if it's being transcoded at the same bitrate. A single 50GB Blu-Ray Remux by itself can take up to approximately 60GB or as little as 15GB, depending on the quality selected. If the transcoding folder is held on the same storage as the database, this must be taken into consideration.
A database for a moderate-sized library can grow anywhere from 10 to 100 GB.
## Cloud
The [transcoding](/docs/general/post-install/transcoding) folder typically requires about the same amount of space as the original media when transcoded at an equivalent bitrate. For example, a single 50 GB Blu-ray remux might consume as much as ~60 GB or as little as ~15 GB after transcoding. If the transcoding folder shares the same storage as the database, this should be accounted for to avoid any problems.
A popular choice for cloud storage has been the program [rclone](https://rclone.org/downloads/). It is supported on most Operating Systems. To facilitate combining local and cloud filesystems, rclone can be paired with another program such as [mergerfs](https://github.com/trapexit/mergerfs). For cloud storage, it is recommended to disable image extraction as this requires downloading the entire file to perform this task.
## Cloud Storage Providers
### MergerFS
[rclone](https://rclone.org/downloads/) is a popular choice for integrating cloud storage with a Jellyfin Server. rclone is supported on most operating systems. To combine local and cloud filesystems, rclone can be paired with another program such as [mergerfs](https://github.com/trapexit/mergerfs).
When using cloud storage, it is recommended to disable image extraction as it requires downloading the entire file.
## MergerFS
MergerFS isn't meant for everything, [see here](https://github.com/trapexit/mergerfs#what-should-mergerfs-not-be-used-for) for more.
- rclone recommended [config](https://forum.rclone.org/t/my-best-rclone-config-mount-for-plex/7441).
To modify and examine your mergerfs mount, here's a quick [guide](https://zackreed.me/mergerfs-neat-tricks).
## Filesystem Considerations
For certain filesystems, optimizations are highly recommended for acceptable performance.
### ZFS
Whilst development is being done on further database providers, in the current implementation of Jellyfin Server, the database uses SQLite. ZFS uses a default record size of `128 K`. This is sub-optimal for the SQLite database.
Ideally, you should use a record size of `4 K` or `8 K` on the dataset that contains your Jellyfin Server SQLite database. This is easily configured when running Jellyfin Server within a Docker container as you are able to easily change bind mounts and can set various datasets for each path as appropriate.
The record size for your media file dataset(s) must not be using `4 K` or `8 K`, otherwise you will likely encounter performance issues as your database scales.
For ZFS datasets containing large media files (i.e., not the dataset containing the Jellyfin Server SQLite database), a record size of `1 M` is likely appropriate for optimal performance.
Note that changing the record size on an existing ZFS dataset will not change the existing data within it, meaning performance will not be any different for anything but newly-written changes into the dataset. As such, it is recommended to rewrite your data into the dataset to take advantage of the change in record size; otherwise, the configuration change will not yield the expected change in performance.
As ZFS snapshots can use a lot of storage over time without a sensible `destroy` schedule, there may be a temptation to keep your data on a mechanical drive instead of an SSD. Do not use ZFS-formatted mechanical drives to store your Jellyfin Server data (everything except your media files), as this will result in poor performance. An SSD is strongly recommended.
@@ -224,7 +224,7 @@ You have 3 options to set the locking mode to:
- `Optimistic` - Defines that all writes should be attempted and should be retried when they fail.
- `Pessimistic` - Defines a behavior that always blocks all reads while any one write is done.
Stop your Jellyin server and navigate to its config directory. There are a lot of xml files, look for the `database.xml` file and edit the `LockingBehavior` option:
Stop your Jellyfin server and navigate to its config directory. There are a lot of xml files, look for the `database.xml` file and edit the `LockingBehavior` option:
```xml
<?xml version="1.0" encoding="utf-8"?>
@@ -236,7 +236,7 @@ Stop your Jellyin server and navigate to its config directory. There are a lot o
</DatabaseConfigurationOptions>
```
then start your jellyfin instance again. If this still does not help with the issues, you can try setting the `LockingBehavior` to `Pessimistic` instead but this comes with a significant performance impact so it is only recommended when `Optimistic` does not help with the issues.
then start your Jellyfin instance again. If this still does not help with the issues, you can try setting the `LockingBehavior` to `Pessimistic` instead but this comes with a significant performance impact so it is only recommended when `Optimistic` does not help with the issues.
### LXC specific issues
+29 -33
View File
@@ -5,7 +5,7 @@ title: Codec Support
# [Codec Tables](https://en.wikipedia.org/wiki/List_of_codecs "Wikipedia's list of all codecs")
The goal is to Direct Play all media. This means the container, video, audio and subtitles are all compatible with the client. If the media is incompatible for any reason, Jellyfin will use FFmpeg to [convert the media](http://howto-pages.org/ffmpeg/) to a format that the client can process. Direct Stream will occur if the audio, container or subtitles happen to not be supported. If the video codec is unsupported, this will result in video transcoding. Subtitles can be tricky because they can cause Direct Stream (subtitles are remuxed) or video transcoding (burning in subtitles) to occur. This is the most intensive CPU component of transcoding. Decoding is less intensive than encoding.
The goal is to Direct Play all media. This means the container, video, audio and subtitles are all compatible with the client. If the media is incompatible for any reason, Jellyfin will [convert the media](http://howto-pages.org/ffmpeg/) to a format that the client can process. Direct Stream will occur if the audio, container or subtitles happen to not be supported. If the video codec is unsupported, this will result in video transcoding. Subtitles can be tricky because they can cause Direct Stream (subtitles are remuxed) or video transcoding (burning in subtitles) to occur. This is the most intensive CPU component of transcoding. Decoding is less intensive than encoding.
## [Video Compatibility](https://en.wikipedia.org/wiki/Comparison_of_video_container_formats "Wikipedia's video codec tables")
@@ -13,46 +13,40 @@ The goal is to Direct Play all media. This means the container, video, audio and
[Test your browser's compatibility for any codec profile.](https://cconcolato.github.io/media-mime-support/)
| Sorted by efficiency (excluding bit depth) | Chrome | Edge | Firefox | Safari | Android | Android TV | iOS | SwiftFin (iOS) | [Roku](https://developer.roku.com/docs/specs/media/streaming-specifications.md) | Kodi | Jellyfin Media Player |
| ------------------------------------------------------------------------------------------------------------------ | -------------- | -------------- | --------------- | --------------- | -------------- | -------------- | -------------- | --------------- | ------------------------------------------------------------------------------- | ---- | --------------------- |
| [MPEG-4 Part 2/SP](https://en.wikipedia.org/wiki/DivX) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ |
| [MPEG-4 Part 2/ASP](<https://en.wikipedia.org/wiki/MPEG-4_Part_2#Advanced_Simple_Profile_(ASP)>) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | | ✅ | ✅ |
| [H.264 8Bit](https://caniuse.com/#feat=mpeg4 'H264 Browser Support Reference') | ✅ | ✅ | | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| [H.264 10Bit](https://caniuse.com/#feat=mpeg4 'H264 Browser Support Reference') | ✅ | ✅ | ❌ | 🔶<sup>12</sup> | ✅ | ✅ | ❌ | ✅ | ❌ | ✅ | ✅ |
| [H.265 8Bit](https://caniuse.com/#feat=hevc 'HEVC Browser Support Reference') | 🔶<sup>8</sup> | ✅<sup>7</sup> | ✅<sup>15</sup> | 🔶<sup>1</sup> | 🔶<sup>2</sup> | ✅<sup>5</sup> | 🔶<sup>1</sup> | ✅<sup>6</sup> | 🔶<sup>9</sup> | ✅ | ✅ |
| [H.265 10Bit](https://caniuse.com/#feat=hevc 'HEVC Browser Support Reference') | 🔶<sup>8</sup> | ✅<sup>7</sup> | ✅<sup>15</sup> | 🔶<sup>1</sup> | 🔶<sup>2</sup> | 🔶<sup>5</sup> | 🔶<sup>1</sup> | ✅<sup>6</sup> | 🔶<sup>9</sup> | ✅ | ✅ |
| [VP9](https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Video_codecs#VP9 'V9 Browser Support Reference') | ✅ | ✅ | ✅ | ✅<sup>10</sup> | ✅<sup>3</sup> | 🔶<sup>3</sup> | ❌ | <sup>13</sup> | ✅ | ✅ | ✅ |
| [AV1](https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Video_codecs#AV1 'AV1 Browser Support Reference') | ✅ | ✅ | ✅ | 🔶<sup>11</sup> | ✅ | 🔶<sup>4</sup> | ❌ | 🔶<sup>14</sup> | ✅ | ✅ | ✅ |
| Sorted by efficiency (excluding bit depth) | Chrome | Edge | Firefox | Safari | Android | Android TV | iOS | SwiftFin (iOS) | Roku | Kodi | Jellyfin Media Player |
| ------------------------------------------------------------------------------------------------------------------ | ------ | -------------- | -------------- | -------------- | ------- | -------------- | --- | -------------- | -------------- | ---- | --------------------- |
| [MPEG-4 Part 2/SP](https://en.wikipedia.org/wiki/DivX) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ |
| [MPEG-4 Part 2/ASP](<https://en.wikipedia.org/wiki/MPEG-4_Part_2#Advanced_Simple_Profile_(ASP)>) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | | ✅ | ✅ |
| [H.264 8Bit](https://caniuse.com/#feat=mpeg4 'H264 Browser Support Reference') | ✅ | ✅ | 🔶<sup>8</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| [H.264 10Bit](https://caniuse.com/#feat=mpeg4 'H264 Browser Support Reference') | ✅ | ✅ | ❌ | 🔶<sup>4</sup> | ✅ | ✅ | ❌ | ✅ | ❌ | ✅ | ✅ |
| [H.265 8Bit](https://caniuse.com/#feat=hevc 'HEVC Browser Support Reference') | 🔶 | 🔶<sup>2</sup> | 🔶<sup>7</sup> | ✅ | 🔶 | ✅ | ✅ | ✅ | 🔶<sup>3</sup> | ✅ | ✅ |
| [H.265 10Bit](https://caniuse.com/#feat=hevc 'HEVC Browser Support Reference') | 🔶 | 🔶<sup>2</sup> | 🔶<sup>7</sup> | ✅ | 🔶 | 🔶 | ✅ | ✅ | 🔶<sup>3</sup> | ✅ | ✅ |
| [VP9](https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Video_codecs#VP9 'V9 Browser Support Reference') | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ⚠️<sup>5</sup> | ✅ | ✅ | ✅ |
| [AV1](https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Video_codecs#AV1 'AV1 Browser Support Reference') | ✅ | ✅ | ✅ | 🔶 | ✅ | 🔶<sup>1</sup> | ❌ | 🔶<sup>6</sup> | ✅ | ✅ | ✅ |
<sup>1</sup>HEVC is only supported in MP4, M4V, and MOV containers.
Legends:<br />
❌=Not Supported.<br />
🔶=Support depends on device and/or settings.<br />
⚠️=Software Decode Only.<br />
✅=Fully supported (Hardware support with software fallback).<br />
<br />
<sup>2</sup>Android playback is currently broken. Client reports that HEVC is supported and attempts to Direct Stream.
This table shows the support status of **recent** client software and OS versions. Legacy versions may differ in support. Remuxing due to container compatibility is considered fully supported for this table. <br /><br />
<sup>1</sup>Needs at least Android TV 10.
<br />
<sup>3</sup>May be (partially) dependent on Hardware support (can be compensated with CPU decoding on Android). Most new Android phones in the higher price range and many "4K" Android TV devices have VP9 hardware decoding support. Refer to you manufacturer for supported codecs.
<sup>2</sup>Windows requires the [HEVC video extension from Microsoft Store](https://apps.microsoft.com/detail/9nmzlz57r3t7).
<br />
<sup>4</sup>Needs at least Android TV 10.
<sup>3</sup>HEVC decoding is only supported on 4K devices.
<br />
<sup>5</sup>As of <a href="https://github.com/jellyfin/jellyfin-androidtv/pull/671">version 0.12</a>, HEVC is enabled on all devices running Android 5.0+, but early generations of the Amazon Fire may not work yet. 10Bit may be supported depending on your device. Before Client 0.12, HEVC support was enabled on specific devices.
<sup>4</sup>Needs to be manually enabled in Settings > Playback > Enable H.264 High 10 Profile. Requires macOS >= 14 and Apple Silicon.
<br />
<sup>6</sup>HEVC decoding is supported on Apple devices with the A8X chip or newer and at least iOS 14.
<sup>5</sup>VP9 is only available with Swiftfin (VLCKit) player.
<br />
<sup>7</sup>HEVC decoding is only supported on Windows 10 with the HEVC Video Extension from the Microsoft <a href="https://www.microsoft.com/store/productId/9NMZLZ57R3T7">store</a>.
<sup>6</sup>AV1 is enabled by default for Swiftfin (VLCKit). AV1 is disabled by default for Native (AVKit). Enabling AV1 may result in a poor experience for older devices.
<br />
<sup>8</sup>Chromium 107 does support HEVC decoding when HEVC hardware decoding is available.
<sup>7</sup>Windows requires the [HEVC video extension from Microsoft Store](https://apps.microsoft.com/detail/9nmzlz57r3t7). Linux requires system ffmpeg for support.
<br />
<sup>9</sup>HEVC decoding is only supported on 4K devices.
<br />
<sup>10</sup>VP9 decoding on Safari requires at least Safari 14.
<br />
<sup>11</sup>AV1 decoding is only available on devices with A17 or M3 series chips or newer and requires at least Safari 17.
<br />
<sup>12</sup>Need to be manually enabled in Settings > Playback > Enable H.264 High 10 Profile. Playback on Apple Silicon Macs with macOS version < 14 and Intel Macs with all macOS versions may result in blank frames if this is enabled.
<br />
<sup>13</sup>VP9 is only availble with Swiftfin (VLCKit) player.
<br />
<sup>14</sup>AV1 is enabled by default for Swiftfin (VLCKit). AV1 is disabled by default but can be enabled for Native (AVKit) using Custom Device Profiles. Enabling AV1 may result in a poor experience for SOCs prior to A17.
<br />
<sup>15</sup>Requires Firefox 134+ for Windows, 136+ for macOS, and 137+ for Linux. On Windows 11 22H2+ and Windows 10 1507-1709, you can play H.265 (HEVC) video natively. Windows 10 1803+ and Windows 11 21H2 need the [HEVC video extension from Microsoft Store](https://apps.microsoft.com/detail/9nmzlz57r3t7). Linux requires system ffmpeg for support.
Some Linux distributions provide a Firefox package that does not have H264 support, causing transcoding to be required. You may need to install additional packages on these system. The most obvious symptom is Jellyfin attempting to transcode to VP9.
[Format Cheatsheet:](https://en.wikipedia.org/wiki/MPEG-4#MPEG-4_Parts)
@@ -198,7 +192,7 @@ If the container is unsupported, this will result in remuxing. The video and aud
| Container | Chrome | Edge | Firefox | Safari | Android | Android TV | Kodi | Roku |
| :-------------------------------------------------------------------: | :----: | :--: | :-----: | :----: | :-----: | :--------: | :--: | :--: |
| [MP4](https://en.wikipedia.org/wiki/MPEG-4_Part_14)<sup>1</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| [MKV](https://en.wikipedia.org/wiki/Matroska)<sup>2, 3, 8</sup> | | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ |
| [MKV](https://en.wikipedia.org/wiki/Matroska)<sup>2, 3, 8, 9</sup> | | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ |
| [WebM](https://en.wikipedia.org/wiki/WebM)<sup>3, 5, 6</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| [TS](https://en.wikipedia.org/wiki/MPEG_transport_stream)<sup>4</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| [OGG](https://en.wikipedia.org/wiki/Ogg)<sup>5, 7</sup> | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
@@ -218,3 +212,5 @@ If the container is unsupported, this will result in remuxing. The video and aud
<sup>7</sup>OGG on Safari requires at least iOS 18.4 / macOS 15.4
<br />
<sup>8</sup>MKV support in Firefox is currently disabled in Jellyfin, as there are significant issues making it unusable for Jellyfin. [1](https://bugzilla.mozilla.org/show_bug.cgi?id=2000420) [2](https://bugzilla.mozilla.org/show_bug.cgi?id=1991746)
<br />
<sup>9</sup>MKV on Chrome requires at least Chrome 145.
+22 -748
View File
@@ -5,21 +5,37 @@ title: CSS Customization
# CSS Customization
In `Dashboard > General`, the "Custom CSS" field can be used to override current CSS in Jellyfin's stylesheet.
Jellyfin allows users to customize the appearance of the web interface by applying custom CSS. This feature is intended for advanced customization and should be used with care. Support is not provided for issues caused by custom CSS.
[Custom CSS](https://developer.mozilla.org/en-US/docs/Web/CSS) provides customization such as changing colors, changing layouts, and item size and behavior. Below is a list of various tweaks that can be applied. The CSS tweaks work on both the web client, and the [Android application](https://play.google.com/store/apps/details?id=org.jellyfin.mobile&hl=en_US). The code will apply in the order that it is written, however `!important` will overrule everything. To learn more about `!important` and more, see [CSS Specificity](https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity) or [specifishity](https://specifishity.com/). To implement these changes, go to `Dashboard > General > Custom CSS` to start.
Custom CSS is only applied to clients that use Jellyfin Web. As a result, it does not affect all Jellyfin clients.
If you have little or no experience with CSS, various resources and tutorials can be found online. Using the tweaks and examples below makes it quite easy to get started with making your own changes to your Jellyfin instance.
:::warning
![Screenshot of the 'Custom CSS' setting in the administrator dashboard of the web client](/images/docs/custom-css-customcssfield.png)
External resources referenced by custom CSS are loaded by the client, not the Jellyfin server. Ensure these resources are accessible from all client devices. If a resource cannot be reached, Jellyfin Web may not render correctly.
Using externally hosted stylesheets, fonts, or other assets can also affect offline functionality, as clients must be able to download those resources when loading the interface.
:::
To add custom CSS, navigate to `Dashboard > Branding` and enter your stylesheet in the "Custom CSS" field. Custom CSS is loaded after Jellyfin's default styles, allowing you to override existing rules and customize elements such as colors, layouts, and sizing.
![Screenshot of the "Custom CSS" setting in the administrator dashboard of the web client](/images/docs/clients/custom-css-admindashboard.png)
Alternatively, custom CSS can be configured on a per-user basis under `Settings > Display`.
![Screenshot of the "Custom CSS" setting in the user settings page](/images/docs/clients/custom-css-usersettings.png)
If you have little or no experience with CSS, consider reviewing additional community resources and tutorials.
## General Information About CSS
You can learn more about CSS using sites like [w3schools](https://www.w3schools.com/css/default.asp) and [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS). Below are some very basic CSS knowledge that will let you do rough edits to the pre-made tweaks below.
CSS rules are applied in the order they are written, although declarations marked with `!important` take precedence over most other rules. For more information, see the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity) on CSS and CSS specificity.
You can learn more about CSS using sites like [w3schools](https://www.w3schools.com/css/default.asp) and [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS). Below is some very basic CSS knowledge that will let you do rough edits.
### Colors
CSS supports multiple color formats, but typically the hex color codes are used for specific colors. To get a specific color, exact color data such as the hex codes below have to be used.
CSS supports multiple color formats, but typically hex color codes are used for specific colors. To get a specific color, exact color data such as the hex codes below have to be used.
Some examples of hex color codes:
@@ -60,745 +76,3 @@ CSS can be "chained" together to modify different sections together at the same
border-color: #d00000;
}
```
## Tweak List
To apply any one of these tweaks, copy and paste the CSS code from the example into the "Custom CSS" field. To use multiple tweaks, simply add them one after another into the field. Any applied code will remain in the field. To remove a tweak, delete or comment out the code for it from the field. Changes apply immediately when the settings page is saved and does not require restarting your Jellyfin server.
### Played Indicator
This will affect the played/watched indicator. Replace the hex color with any value you like.
### Indicators Without Tweak
![Screenshot of the default watched indicators](/images/docs/custom-css-normalwatched.png)
### Green Indicators
```css
/* Make watched icon green */
.playedIndicator {
background: #5dd000;
}
```
![Screenshot of watched indicators with a custom green color applied](/images/docs/custom-css-greenwatched.png)
### Transparent And Dark Indicators
```css
/* Make watched icon dark and transparent */
.playedIndicator {
background: #00000058 !important;
}
```
![Screenshot of watched indicators with a custom transparent color applied](/images/docs/custom-css-transparentwatched.png)
### Transparant count indicators (eg. Series)
```css
/* Make count indicator icon dark and transparent */
.countIndicator {
background: #00000058;
}
```
### Display external links in mobile layout
The mobile app disables display of external links to IMDb, TheMovieDB, Trakt, etc by default.
To enable the external links again, add the following snippet:
```css
.layout-mobile .itemExternalLinks {
display: block !important;
}
```
### Hide Home Icon from Header
```css
.headerHomeButton {
display: none;
}
.headerButton.headerButtonRight.headerUserButton.paper-icon-button-light {
display: none;
}
```
### Hide Cast Icon from Header
```css
.headerCastButton {
display: none;
}
```
### Hide Sync Icon from Header
```css
.headerSyncButton {
display: none;
}
```
### Hide User Settings from Header
```css
.material-icons.person {
display: none;
}
```
### Hide Live TV Channel Listings
```css
.guideChannelNumber {
display: none;
}
```
### Reduce Live TV Channel Width
```css
.channelsContainer {
max-width: 8em;
}
```
### Hide Cast & Crew
```css
#castCollapsible {
display: none;
}
```
### Hide More Like This
```css
#similarCollapsible {
display: none;
}
```
### Hide Next Up
```css
div.nextUpSection {
display: none;
}
```
### Hide Star Ratings
```css
div.starRatingContainer {
display: none;
}
```
### Replace "Latest Movies" text with Custom Text such as "Recently Added Movies"
```css
#homeTab
> div
> div.section2
> div:nth-child(1)
> div.sectionTitleContainer.sectionTitleContainer-cards.padded-left
> a
> h2 {
display: none;
}
#homeTab
> div
> div.section2
> div:nth-child(1)
> div.sectionTitleContainer.sectionTitleContainer-cards.padded-left
> a
> span {
display: none;
}
#homeTab
> div
> div.section2
> div:nth-child(1)
> div.sectionTitleContainer.sectionTitleContainer-cards.padded-left
> a:after {
content: 'Recently Added Movies ';
font-size: 24px;
font-weight: normal;
}
```
### Replace Latest TV Shows text with Custom Text such as "Recently Added TV Shows"
```css
#homeTab
> div
> div.section2
> div:nth-child(2)
> div.sectionTitleContainer.sectionTitleContainer-cards.padded-left
> a
> h2 {
display: none;
}
#homeTab
> div
> div.section2
> div:nth-child(2)
> div.sectionTitleContainer.sectionTitleContainer-cards.padded-left
> a
> span {
display: none;
}
#homeTab
> div
> div.section2
> div:nth-child(2)
> div.sectionTitleContainer.sectionTitleContainer-cards.padded-left
> a:after {
content: 'Recently Added TV Shows ';
font-size: 24px;
font-weight: normal;
}
```
### Background Image on Login Page
```css
#loginPage {
background: url('https://i.ytimg.com/vi/avCWDDox1nE/maxresdefault.jpg');
background-size: cover;
}
```
### Background Image on Homepage
```css
.backdropImage {
display: none;
}
.backgroundContainer {
background-color: rgba(0, 0, 0, 0);
background-image: url('https://i.ytimg.com/vi/avCWDDox1nE/maxresdefault.jpg');
filter: blur(10px);
background-size: cover;
}
```
[Additional MDN Documentation](https://developer.mozilla.org/en-US/docs/Web/CSS/background)
### Transparent Top Menu
```css
.skinHeader.focuscontainer-x.skinHeader-withBackground.skinHeader-blurred {
background: none;
background-color: rgba(0, 0, 0, 0);
}
.skinHeader.focuscontainer-x.skinHeader-withBackground.skinHeader-blurred.noHomeButtonHeader {
background: none;
background-color: rgba(0, 0, 0, 0);
}
```
### Image Edge Rounded
```css
.cardContent-button,
.itemDetailImage {
border-radius: 0.25em;
}
```
### Enlarge Tab Buttons
Enlarges the tab buttons, suggested, genres, etc. By default they are really tiny, especially on mobile.
```css
/* Adjust both "size-adjust" and "size" to modify size */
.headerTabs.sectionTabs {
text-size-adjust: 110%;
font-size: 110%;
}
.pageTitle {
margin-top: auto;
margin-bottom: auto;
}
.emby-tab-button {
padding: 1.75em 1.7em;
}
```
**The enlarged tab buttons and transparent menu look like this:**
![Screenshot of enlarged tab buttons and transparent menu](/images/docs/custom-css-transparenttopbarenlargedtabs.png)
### Minimalistic Login Page
This looks even better together with the transparent top menu!
```css
/* Narrow the login form */
#loginPage .readOnlyContent,
#loginPage form {
max-width: 22em;
}
/* Hide "please login" text, margin is to prevent login form moving too far up */
#loginPage h1 {
display: none;
}
#loginPage .padded-left.padded-right.padded-bottom-page {
margin-top: 50px;
}
/* Hide "manual" and "forgot" buttons */
#loginPage .raised.cancel.block.btnManual.emby-button {
display: none;
}
#loginPage .raised.cancel.block.btnForgotPassword.emby-button {
display: none;
}
```
![Screenshot of the minimalistic login page](/images/docs/custom-css-minimallogin.png)
### Stylized Episode Previews
The episode previews in season view are sized based on horizontal resolution. This leads to a lot of wasted space on the episode summary and a high vertical page, which requires a lot of scrolling. This code reduces the height of episode entries, which solves both problems.
```css
/* Size episode preview images in a more compact way */
.listItemImage.listItemImage-large.itemAction.lazy {
height: 110px;
}
.listItem-content {
height: 115px;
}
.secondary.listItem-overview.listItemBodyText {
height: 61px;
margin: 0;
}
```
![Screenshot of a TV show page with stylized episode previews](/images/docs/custom-css-episodepreview.png)
### Stylized and Smaller Cast & Crew Info
This will drastically change the style of cast info into something very similar to how Plex approaches it. This override will lead to somewhat smaller thumbnails, and also works with all themes.
```css
/* Shrink and square (or round) cast thumbnails */
#castContent .card.overflowPortraitCard.personCard.card-hoverable.card-withuserdata {width: 4.2cm !important; font-size: 90% !important;}
#castContent .card.overflowPortraitCard.personCard.card-withuserdata {width: 4.2cm !important; font-size: 90% !important;}
/* Correct image aspect ratio behavior, set border-radius to zero for square tiles */
#castContent .cardContent-button.cardImageContainer.coveredImage.cardContent.cardContent-shadow.itemAction.lazy {background-size: cover; !important; border-radius: 2.5cm;}
#castContent .cardContent-button.cardImageContainer.coveredImage.defaultCardBackground.defaultCardBackground1.cardContent.cardContent-shadow.itemAction {background-size: cover; !important; border-radius: 2.5cm;}
#castContent .cardContent-button.cardImageContainer.coveredImage.defaultCardBackground.defaultCardBackground2.cardContent.cardContent-shadow.itemAction {background-size: cover; !important; border-radius: 2.5cm;}
#castContent .cardContent-button.cardImageContainer.coveredImage.defaultCardBackground.defaultCardBackground3.cardContent.cardContent-shadow.itemAction {background-size: cover; !important; border-radius: 2.5cm;}
#castContent .cardContent-button.cardImageContainer.coveredImage.defaultCardBackground.defaultCardBackground4.cardContent.cardContent-shadow.itemAction {background-size: cover; !important; border-radius: 2.5cm;}
#castContent .cardContent-button.cardImageContainer.coveredImage.defaultCardBackground.defaultCardBackground5.cardContent.cardContent-shadow.itemAction {background-size: cover; !important; border-radius: 2.5cm;}
#castContent .cardScalable {width: 3.8cm !important; height: 3.8cm !important; border-radius: 2.5cm;}
#castContent .cardOverlayContainer.itemAction {border-radius: 2.5cm;}
/* Center the mouseover buttons */
#castContent .cardOverlayButton-br {bottom: 4%; right: 15%; width: 70%;}
#castContent .cardOverlayButton.cardOverlayButton-hover.itemAction.paper-icon-button-light {margin:auto;}
```
![Screenshot of stylized and smaller Cast & Crew info](/images/docs/custom-css-stylizedcast.png)
### Pictureless Cast & Crew
```css
#castContent .card.overflowPortraitCard {
width: 4.2cm;
font-size: 90%;
}
#castContent .personCard {
width: auto;
}
#castContent .personCard .cardBox {
margin-bottom: 0px;
margin-right: 0px;
}
#castContent {
flex-wrap: wrap;
max-height: 9.75em;
}
div.personCard > :first-child > :first-child {
display: none;
}
.itemDetailPage .cardText {
text-align: left;
}
.itemDetailPage .textActionButton {
text-align: left;
}
```
![Screenshot of Pictureless Cast & Crew info](/images/docs/custom-css-nopicturecast.png)
### Custom Background Color
```css
.backgroundContainer,
.dialog,
html {
background-color: #0fd0d0;
}
```
### Darken the Background
This darkens the background on Blue Radiance and Purple Haze, edit the percentage depending how dark you want it. Lower is darker.
```css
/* Darken background, only works with blue radiance */
.backgroundContainer {
background-color: #000000;
filter: brightness(50%);
}
```
### Right Header Color
This modifies the colors of the cast, search and user buttons in the top right.
```css
.headerRight {
color: yellow;
}
```
![Screenshot of a custom yellow color for the icon buttons in the top right of the screen](/images/docs/custom-css-rightheader.png)
### Console Panel Custom Color
Modifies the color of the left menu panel.
```css
.mainDrawer-scrollContainer {
color: yellow;
}
```
![Screenshot of a custom yellow color on the left menu panel](/images/docs/custom-css-consolepanel.png)
### General Page Custom Color
```css
.dashboardGeneralForm {
color: yellow;
}
```
![Screenshot of a custom yellow color on the General Page](/images/docs/custom-css-generalcolor.png)
### Custom Border Color
This will change the border color for text fields and drop-down menus.
```css
.emby-input,
.emby-textarea,
.emby-select {
border-color: #d00000;
}
```
This will affect the border color of highlighted (selected) text fields and drop-down menus.
```css
.emby-input:focus,
.emby-textarea:focus,
.emby-select-withcolor {
border-color: #ffffff !important;
}
```
![Screenshot of a custom red border color](/images/docs/custom-css-bordercolor.png)
### Full Header Tweak
```css
.skinHeader,
.mainDrawer,
.emby-input,
.emby-textarea,
.emby-select,
.navMenuOption-selected,
.cardBox,
.paperList {
background: #ff9475;
}
```
![Screenshot of the full header tweak](/images/docs/custom-css-full-header-mod.png)
### Disable Image Carousel for Libraries
This will make it so libraries and media fit neatly onto the homepage with no left to right scrolling required.
```css
@media all and (min-width: 50em) {
.homePage .emby-scroller {
margin-right: 0;
}
.homePage .emby-scrollbuttons {
display: none;
}
.homePage .itemsContainer {
flex-wrap: wrap;
}
}
```
### Shift Scroller Buttons
```css
.emby-scrollbuttons {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
padding: 0;
justify-content: space-between;
pointer-events: none;
}
.emby-scrollbuttons-button {
pointer-events: initial;
}
```
### "Hotdogs and Catsup" Color Theme Example
An example of a color theme.
![Screenshot of the "Hotdogs and Catsup" color theme](/images/docs/custom-css-hotdog-and-catsup.png)
```css
.skinHeader,
.mainDrawer,
.emby-input,
.emby-textarea,
.emby-select,
.navMenuOption-selected,
.cardBox,
.paperList {
background: #ff9475;
}
.emby-input,
.emby-textarea,
.emby-select {
border-color: #fdbe7d;
}
.backgroundContainer.withBackdrop,
.backdropContainer,
.backgroundContainer {
background: #fdbe7d;
}
#myPreferencesMenuPage .listItemBodyText,
.emby-tab-button[data-index='0'],
#myPreferencesMenuPage > div > div > div > a:nth-child(odd),
.button-submit,
.mainAnimatedPage *:nth-child(odd),
.dashboardGeneralForm *:nth-child(odd),
.mainDrawer-scrollContainer *:nth-child(odd),
.headerRight *:nth-child(odd) {
color: red;
}
#myPreferencesMenuPage .listItemIcon,
.emby-tab-button[data-index='1'],
#myPreferencesMenuPage > div > div > div > a:nth-child(even),
.mainAnimatedPage *:nth-child(even),
.dashboardGeneralForm *:nth-child(even),
.mainDrawer-scrollContainer *:nth-child(even),
.headerRight *:nth-child(even) .cancel {
color: yellow;
}
```
### Floating Now Playing Controls
![Screenshot of the floating "Now Playing" controls](/images/docs/custom-css-floatingnowplaying.png)
```css
/* fixed height for the bottom row */
:root {
--element-fixed-top: 95px;
}
/* Now playing bar in the footer */
.nowPlayingBar {
width: 650px;
z-index: 10;
position: fixed;
top: 300px;
height: 120px;
border-style: solid;
border-color: white;
background-color: black;
margin-left: 50%;
}
/* Only child of nowPlayingBar */
.nowPlayingBarTop {
height: 5px !important;
max-width: 500px
top: 10px;
}
/* Song progress seekbar */
.nowPlayingBarPositionContainer {
position: relative;
top: 1.0em !important;
}
/* Container that holds album thumbnail, artist and album name */
.nowPlayingBarInfoContainer {
position: fixed !important;
left: 12px;
top: 34px;
height: 60px;
width: 1100px;
}
/* Holds the next, previous track, play/pause, next and time elements */
.nowPlayingBarCenter {
position: relative !important;
left: 32px;
top: var(--element-fixed-top);
min-width: 500px;
}
/* Hold mute, volume slider container, repeat, favorite and remote control buttons */
.nowPlayingBarRight {
width: 402px !important;
left: -60px;
}
/* Mute button */
.muteButton {
position: relative;
top: var(--element-fixed-top);
}
/* Volume slider */
.nowPlayingBarVolumeSliderContainer {
position: relative;
left: -4px;
top: var(--element-fixed-top);
}
/* Toggle repeat */
.toggleRepeatButton {
position: relative !important;
left: -20px;
top: var(--element-fixed-top);
}
/* Favorite */
.nowPlayingBarUserDataButtons {
position: relative;
left: -4px;
top: var(--element-fixed-top);
}
/* Remote control */
.remoteControlButton {
left: -110px;
top: var(--element-fixed-top);
}
```
### Change Icon Pack
You can choose between Material Icons (Icon Pack used by Jellyfin) and Fontawesome icons.
Material Icons:
- Outlined:
```css
@import url("https://cdn.jsdelivr.net/gh/prayag17/Jellyfin-Icons/Outline.css");
```
- Rounded:
```css
@import url("https://cdn.jsdelivr.net/gh/prayag17/Jellyfin-Icons/round.css");
```
- Sharp:
```css
@import url("https://cdn.jsdelivr.net/gh/prayag17/Jellyfin-Icons/Sharp.css");
```
Fontawesome Icons:
- Solid:
```css
@import url("https://cdn.jsdelivr.net/gh/prayag17/Jellyfin-Icons/Font%20Awesome/solid.css");
```
- Regular:
```css
@import url("https://cdn.jsdelivr.net/gh/prayag17/Jellyfin-Icons/Font%20Awesome/regular.css");
```
- Light:
```css
@import url("https://cdn.jsdelivr.net/gh/prayag17/Jellyfin-Icons/Font%20Awesome/light.css");
```
- duotone:
```css
@import url("https://cdn.jsdelivr.net/gh/prayag17/Jellyfin-Icons/Font%20Awesome/duotone.css");
```
## Community Links
Some links to places where custom CSS has been discussed and shared!
### Community Posts
Keep in mind that these posts may have been made under previous versions of Jellyfin. Some of these tweaks listed in these guides may not work anymore!
- [Custom CSS Guide](https://www.reddit.com/r/jellyfin/comments/fgmu6k/custom_css_updated_for_1050)
- ["But wait, there is more Custom CSS!"](https://www.reddit.com/r/jellyfin/comments/htrfrx/but_wait_there_is_more_custom_css)
- [Customizable Plug n' Play CSS for Jellyfin](https://www.reddit.com/r/jellyfin/comments/g9gmjj/customizable_plug_n_play_css_for_jellyfin)
- [Easy Jellyfin custom CSS](https://www.reddit.com/r/jellyfin/comments/crxqk5/easy_jellyfin_custom_css)
- [Custom CSS - updated for 10.5.0](https://www.reddit.com/r/jellyfin/comments/fgmu6k/custom_css_updated_for_1050)
- [Sharing even more custom CSS (and some fixes to previous stuff)](https://www.reddit.com/r/jellyfin/comments/bvnt65/sharing_even_more_custom_css_and_some_fixes_to)
- [Posting my Jellyfin Custom CSS](https://www.reddit.com/r/jellyfin/comments/p13yqg/posting_my_jellyfin_custom_css/)
### Community Themes
- [Ultrachromic - A custom theme for Jellyfin mediaserver created using CSS overrides](https://github.com/CTalvio/Ultrachromic)
- [JellySkin - Vibrant Jellyfin theme with a lot a animations](https://github.com/prayag17/JellySkin)
- [JellyFlix - The Best Netflix Clone for Jellyfin](https://github.com/prayag17/JellyFlix)
- [Jellyfin Netflix Dark - The Best Netflix Dark Theme for Jellyfin Around!](https://github.com/DevilsDesigns/Jellyfin-Netflix-Dark)
- [Dark and Green - A Emby like night mode skin](https://github.com/mbcooper83/jellyfin-css-darkandgreen)
- [Hint of Green](https://github.com/looi-wh/HintOfGreenCSS)
- [Scyfin - A modern Jellyfin theme](https://github.com/loof2736/scyfin)
+1 -1
View File
@@ -28,7 +28,7 @@ The installation method for the repository varies depending on what kind of devi
- If prompted, enter settings and enable "Unknown Sources", then go back to the Add-on Browser
- Select the newly downloaded file and it will be installed
#### "Embedded" Devices (Android TV, Firestick, and other TV Boxes)
#### "Embedded" Devices (Android TV, FireTV Stick, and other TV Boxes)
1. Open Kodi, go to the settings menu, and navigate to "File manager"
- Select "Add source"
+13 -2
View File
@@ -17,7 +17,11 @@ Summarized here are the two biggest ones, one for backend devs and another for f
Note that each of the repositories also has its own documentation on how to get started with that project, generally found in the repository README. You can also view the organization [source tree](/docs/general/contributing/source-tree) to see how some of the bigger projects are structured.
The best way to get going on some actual development is to look through the [issues list](https://github.com/jellyfin/jellyfin/issues) of the associated repository, find an issue you would like to work on, and start hacking! Issues are triaged regularly by the administrative team, and labels assigned that should help you find issues within your skill-set. Once you start working on an issue, please comment on it stating your intent to work on the issue, to avoid unnecessary duplication of work.
The best way to get going on some actual development is to look through the [issues list](https://github.com/jellyfin/jellyfin/issues) of the associated repository, find an issue you would like to work on, and start hacking! Issues are triaged regularly by the administrative team, and labels assigned that should help you find issues within your skill-set.
### Feature Proposals
New features or substantial changes to existing behavior affecting multiple sub-projects should first be proposed as a [Jellyfin Meta discussion](https://github.com/jellyfin/jellyfin-meta/discussions).
### Major Issue Types
@@ -58,7 +62,14 @@ The first step is to set up a copy of the Git repository of the project you want
5. Build the Jellyfin Web project with NPM, and copy the location of the resulting `dist` folder.
6. In your `Jellyfin.Server` project add an environment variable named `JELLYFIN_WEB_DIR` with the value set to the full path of your `dist` folder.
6. In your `Jellyfin.Server` project add an environment variable named `JELLYFIN_WEB_DIR` with the value set to the full path of your `dist` folder. You can set this path in your project by modifying the **environmentVariables** in the `Jellyfin.Server/Properties/launchSettings.json` file:
```json
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"JELLYFIN_WEB_DIR": "/path/to/your/jellyfin-web/dist"
}
```
You will now be ready to begin building or modifying the project.
+1 -1
View File
@@ -43,7 +43,7 @@ When writing a bug issue, please ensure you capture as much relevant detail as p
Bugs should be tagged with `[bug]` at the beginning of their title. This will later be removed by the Jellyfin team when assigning labels. To assist in triaging, if you know which other [label(s)](/docs/general/contributing/issues#issue-labels) should be applied to your issue, please add them after the `[bug]` label.
Bugs should be reproduceable. That is, you should be able to have determined through troubleshooting how to replicate the issue. While one-time bugs should not be ignored, if they're difficult or impossible to reproduce, it's likely very hard to fix them. Please attempt to reproduce the bug before filing the issue and include the smallest test case you can to demonstrate it.
Bugs should be reproducible. That is, you should be able to have determined through troubleshooting how to replicate the issue. While one-time bugs should not be ignored, if they're difficult or impossible to reproduce, it's likely very hard to fix them. Please attempt to reproduce the bug before filing the issue and include the smallest test case you can to demonstrate it.
If you ever need assistance for troubleshooting or opening an issue, please [contact the community](/docs/general/getting-help) and we'll try to help you out!
+49
View File
@@ -0,0 +1,49 @@
---
uid: llm-policies
title: LLM/"AI" Policies
---
# Jellyfin LLM/"AI" Development Policy
The rise of LLMs as a useful development tool over the last year or so has been significant. The power and flexibility of tools like Claude Code and ChatGPT have given a lot of functionality both to experienced developers and new developers alike. But there are trade-offs.
The Jellyfin project has, from day one, had a major focus on code quality - readability, simplicity, conciseness. This is a mostly manual effort driven by a dedicated team of individuals, and is motivated by a desire to fix the code Jellyfin is based off of which, without beating a dead horse too much, was extremely fragile, spaghettified, and prone to over-engineered complexity.
We are seeing a precipitous rise in contributors using AI within the Jellyfin ecosystem, both in the server and for clients, as well as a rise in criticism and concern about LLMs generally. At this time we are writing this policy to address exactly what we expect and desire with respect to contributions and interactions within our community that may use LLMs. These rules apply to all of our official projects and community spaces.
## General Guidelines
1. LLM output is **expressly prohibited** for any direct communication, including the following:
* issues or comments
* feature requests or comments
* pull request bodies or comments
* forum/chat/etc. posts or comments
In short, if you are posting **any** of those things, the output must be your own words, explanation, description, etc., not a verbatim dump of an LLM's output. We expect you to understand what you're posting. Violating this rule will result in closure/deletion of the offending item(s).
An exception will be made for **LLM-assisted translations** if you are having trouble accurately conveying your intent in English. Please explicitly note this ("I have translated this from MyLanguage with an LLM") and, if possible, post in your original language as well.
2. LLM code contributions are subject to more granularity below, but the general principle is that "pure 'vibe coding' will be rejected" and "you are responsible for what you commit". We will review in that vein. If the **code looks terrible**, it will be **rejected as such**.
## LLM Code Contributions to Official Projects
The use of LLMs for code is controversial and open to much interpretation. These guidelines are our best effort attempt to ensure that knowledgeable developers who seek to use these tools as a legitimate aid are not overly-hindered, while also preventing an ongoing flood of slop contributions that violate our core ethos above. These apply to **all official Jellyfin projects**.
1. Contributions should be **concise and focused**. If the PR claims to target X, and is also touching unrelated Y and Z, it will be rejected. This includes incidental changes to unrelated functionality, a hallmark of poorly-worded or too-general prompts. Similarly, a large PR must be **broken into multiple small, manageable commits** for review and history purposes.
2. Formatting and quality **standards must be upheld**. Excessive unhelpful comments, spaghetti code, spaces on empty lines, etc. will be interpreted as pure LLM output and rejected; you must **clean up the mess** before submitting. Also **do not commit LLM metafiles** (e.g. `.claude` configs) or any other editor-created non-code files.
3. You must **review the output** and be able to **explain** in the PR body - **without** LLM output as noted above - **what is being changed and why**. Your PR body (and, if applicable, commit bodies) should be providing context to other developers about why a change was made, and if your name is on it, we want **your** words and explanations, not an LLM's. If **you can't explain** what the LLM did, we are **not interested** in the change.
4. The changes must be **tested**. The code should build and run correctly, or it will be rejected. You should also **explicitly test the functionality being modified**.
5. You must be able and willing to **handle review feedback** and implement the suggested change(s) as required. What this means in practice is, if you do not know what has been changed or why (see #3), and thus can't implement suggested changes or discuss them **yourself**, then we are **not interested** in the change. Just dumping reviewer feedback into an LLM and expecting what comes out to be "good enough", is not.
6. **Features or refactors** require **an in-depth level of understanding** about what is being changed and why. It is obvious to our reviewers when changes are made without the developer making them understanding what is happening. These will be rejected. And as noted in #1, the PR must **contain multiple discrete commits**. _We_ will squash commits as deemed appropriate after review. Large changes must also follow our other development policies (discussion, review, implementation, testing process).
7. The **final discretion always lies with the reviewers**. If your PR is not capable of being reasonably reviewed, for any reason (over-complexity, size, squashed commits, etc.) it will be rejected, and this goes just as much for non-LLM-assisted PRs as it does for LLM-assisted PRs. You will be asked to split such a PR up into multiple PRs that each present a focused, concise set of changes instead.
The golden rule is this: **do not just let an LLM loose on the codebase with a vague vibe prompt and then commit the results as-is**. This is lazy development, will **always** result in a **poor-quality contribution** from our perspective, and we are not at all interested in such slop. **Make an effort** or please do not bother. And again, you are free to use LLMs to **assist** you, but not as the sole source of code changes.
## LLM-generated Tools, Clients, etc. Shared in the Community
You are of course free to do whatever you wish for your own non-official projects. However, we will be enforcing the following rules for any **sharing of such projects within our communities**.
1. Any primarily-LLM-developed projects should be **clearly marked as such**. It is up to users to decide if this is acceptable to them or not. If you used an LLM for secondary assistance (e.g. docs, formatting, etc.) in an obvious way, we would err towards disclosure as well.
2. You **must** respect and follow licenses. If you are basing your project off of existing code, **following its license is not optional**. You must **credit existing contributors in full** for **all contributions**. Do not **mangle the Git history**, and do not **commit pending 3rd party changes as your own** (i.e. by copying the code and then committing it). Doing so will result in, not just rejection, but a ban from our organization and community. We have a **zero tolerance policy** for code theft and bad-faith attribution attempts.
3. For members of the community, **do not report** LLM-generated tools, clients, etc. **on that basis alone**, and do not engage in anti-LLM "witch hunts". As mentioned above, this is **permitted** and it is your choice whether to "support" said tool/client/etc. or not.
4. We, the moderators, are not going to play "LLM police" about 3rd party projects by nitpicking to try to "find LLM contributions" that otherwise follow our rules here; this is tedious and a waste of our time and effort. What this means in practice is that rule #1 is up to the author, and rule #3 must be interpreted in that vein. If you **only suspect** a tool is LLM-generated and violates rule #1, then downvote/ignore it and move on. **Only if** we see **blatant breaking of rule #1** we will enforce it, but again we will not be going through code line by line playing the "was this LLM generated?" game. Rule #2 will always be enforced regardless of LLM-ness or not.
@@ -2,19 +2,6 @@
[Docker](https://www.docker.com/) allows you to run containers on Linux, Windows and MacOS.
:::warning
If you wish to use Windows or macOS, please install Jellyfin natively instead. [Windows](/docs/general/installation/windows) [macOS](/docs/general/installation/macos).
While it is possible to run Jellyfin in Docker on a Windows or macOS host, it is NOT supported. Some features are known to be broken when running in Docker on platforms other than Linux, Notably:
- Hardware Accelerated Transcoding
- [Scanning on macOS in Docker](https://github.com/jellyfin/jellyfin/issues/13093)
You WILL NOT receive any support for running Jellyfin in Docker on platforms other than Linux.
:::
The basic steps to create and run a Jellyfin container using Docker are as follows.
1. Follow the [official installation guide to install Docker](https://docs.docker.com/engine/install).
@@ -1,18 +1,5 @@
<!-- markdownlint-disable MD041 -->
:::warning
If you wish to use Windows or macOS, please install Jellyfin natively instead. [Windows](/docs/general/installation/windows) [macOS](/docs/general/installation/macos).
While it is possible to run Jellyfin in Docker on a Windows or macOS host, it is NOT supported. Some features are known to be broken when running in Docker on platforms other than Linux, Notably:
- Hardware Accelerated Transcoding
- [Scanning on macOS in Docker](https://github.com/jellyfin/jellyfin/issues/13093)
You WILL NOT receive any support for running Jellyfin in Docker on platforms other than Linux.
:::
Create a `docker-compose.yml` file like the following.
```yml
@@ -29,7 +29,7 @@ Steps to run Jellyfin using Podman are similar to the Docker steps.
3. Open the necessary ports in your machine's firewall if you wish to permit access to the Jellyfin server from outside the host.
This is not done automatically when using rootless Podman.
If your distribution uses `firewalld`, the following commands save and load a new firewall rule opening the HTTP port `8096` for TCP connections. Additionaly port 7359 UDP needs to be opened for auto discovery.
If your distribution uses `firewalld`, the following commands save and load a new firewall rule opening the HTTP port `8096` for TCP connections. Additionally port 7359 UDP needs to be opened for auto discovery.
```sh
sudo firewall-cmd --add-port=8096/tcp --permanent
@@ -0,0 +1,307 @@
---
uid: installation-advanced-kubernetes
title: Kubernetes Deployment
description: Deploy Jellyfin on Kubernetes using Helm
sidebar_position: 7
---
# Kubernetes Deployment
This guide covers deploying Jellyfin on Kubernetes using the [official Helm chart](https://github.com/jellyfin/jellyfin-helm/tree/master/charts/jellyfin).
## Prerequisites
- Kubernetes cluster (v1.19+)
- Helm 3.x installed
- `kubectl` configured for your cluster
- Sufficient storage for media and configuration
- Ingress controller (e.g. traefik) for external access (required for this tutorial, see [official docs](https://github.com/jellyfin/jellyfin-helm/tree/master/charts/jellyfin) for alternatives)
## Installation
### 1. Add Helm Repository
```bash
helm repo add jellyfin https://jellyfin.github.io/jellyfin-helm
helm repo update
```
### 2. Custom Installation
For complete installation instructions and configuration options, see the [official Jellyfin Helm chart repository](https://github.com/jellyfin/jellyfin-helm/tree/master/charts/jellyfin).
Create a `values.yaml` file for customization:
```yaml
# values.yaml
replicaCount: 1
image:
pullPolicy: IfNotPresent
persistence:
config:
enabled: true
size: 5Gi
storageClass: ''
media:
enabled: true
size: 100Gi
storageClass: ''
ingress:
enabled: true
className: 'traefik'
hosts:
- host: jellyfin.example.com
paths:
- path: /
pathType: Prefix
resources:
limits:
cpu: 2000m
memory: 4Gi
requests:
cpu: 500m
memory: 1Gi
nodeSelector: {}
tolerations: []
affinity: {}
```
Install with custom values:
```bash
helm install jellyfin jellyfin/jellyfin -f values.yaml
```
## Configuration Options
### Service Types
This guide covers ClusterIP service type (default) for internal access only, with external access via ingress controller. Alternatives include LoadBalancer and NodePort services.
### Persistence
#### Using Existing Persistent Volume Claims
```yaml
persistence:
config:
enabled: true
existingClaim: 'jellyfin-config-pvc'
media:
enabled: true
existingClaim: 'jellyfin-media-pvc'
```
#### Creating New PVCs via Helm
```yaml
persistence:
config:
enabled: true
size: 5Gi
storageClass: 'fast-ssd'
media:
enabled: true
size: 100Gi
storageClass: 'slow-hdd'
```
### Ingress
#### Basic Ingress Configuration
```yaml
ingress:
enabled: true
className: 'traefik'
hosts:
- host: jellyfin.example.com
paths:
- path: /
pathType: Prefix
```
#### Advanced Ingress with TLS
```yaml
ingress:
enabled: true
className: 'traefik'
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.middlewares: default-jellyfin-buffering@kubernetescrd
hosts:
- host: jellyfin.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: jellyfin-tls
hosts:
- jellyfin.example.com
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: jellyfin-buffering
namespace: default
spec:
buffering:
maxRequestBodyBytes: 0
```
## Accessing Jellyfin
### Port Forwarding (Development)
```bash
kubectl port-forward svc/jellyfin 8096:8096
```
Access at: `http://localhost:8096`
### External Access
Once ingress is configured, access Jellyfin at your configured domain (e.g., `https://jellyfin.example.com`).
## Monitoring
### Health Checks
The chart includes readiness and liveness probes:
```yaml
livenessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 5
periodSeconds: 5
```
### Metrics
Enable Prometheus metrics if available:
```yaml
metrics:
enabled: true
serviceMonitor:
enabled: true
```
## Troubleshooting
### Common Issues
1. **Permission Denied**: Ensure proper security context for media access
2. **Storage Issues**: Verify persistent volume claims are bound
3. **Network Access**: Check service type and ingress configuration
### Debug Commands
```bash
# Check pod status
kubectl get pods -l app.kubernetes.io/name=jellyfin
# View logs
kubectl logs -f deployment/jellyfin
# Check service
kubectl get svc jellyfin
# Describe pod for events
kubectl describe pod -l app.kubernetes.io/name=jellyfin
```
## Upgrading
```bash
# Update repository
helm repo update
# Upgrade installation
helm upgrade jellyfin jellyfin/jellyfin
# Check upgrade status
helm status jellyfin
```
## Uninstalling
```bash
# Remove Helm release
helm uninstall jellyfin
# Clean up persistent volumes (if needed)
kubectl delete pvc -l app.kubernetes.io/name=jellyfin
```
## Advanced Configuration
### Hardware Acceleration
For GPU acceleration, add device access and security context:
```yaml
securityContext:
privileged: true
resources:
limits:
gpu.intel.com/i915: 1
# or nvidia.com/gpu: 1
volumes:
- name: dri
hostPath:
path: /dev/dri
volumeMounts:
- name: dri
mountPath: /dev/dri
```
### Multiple Media Sources
Mount multiple media sources using additional volumes:
```yaml
volumes:
- name: movies
persistentVolumeClaim:
claimName: movies-pvc
- name: tv
persistentVolumeClaim:
claimName: tv-pvc
volumeMounts:
- name: movies
mountPath: /movies
- name: tv
mountPath: /tv
```
### Custom Environment Variables
```yaml
extraEnvVars:
- name: JELLYFIN_PublishedServerUrl
value: 'https://jellyfin.example.com'
- name: JELLYFIN_CACHE_DIR
value: '/cache'
```
For more configuration options, see the [Jellyfin Helm chart documentation](https://github.com/jellyfin/jellyfin-helm/tree/master/charts/jellyfin).
@@ -527,7 +527,7 @@ You can also pull new images to use in the future.
You can choose to pull from Jellyfin's [Docker Hub](https://hub.docker.com/r/jellyfin/jellyfin) or [GitHub Container Registry](https://github.com/jellyfin/jellyfin/pkgs/container/jellyfin).
- To pull from Docker Hub, use: `jellyfin/jellyin`
- To pull from Docker Hub, use: `jellyfin/jellyfin`
- To pull from from GHCR, use: `ghcr.io/jellyfin/jellyfin`
- [You can check this blog post for more info about GHCR:](/posts/jellyfin-release-10.9.0#key-release-notesbreaking-changes)
- "Docker users: We now offer GitHub Container Registry (GHCR) as an alternative container registry in addition to Docker Hub. You can pull images from the new registry via URIs like `ghcr.io/jellyfin/jellyfin:latest`. Don't worry, we have no plans to drop Docker Hub as a container registry, but we feel providing both gives users more choice and flexibility."
@@ -0,0 +1,61 @@
---
uid: installation-advanced-windows
title: Windows Service
description: Installing Jellyfin as a Windows Service.
sidebar_position: 5
---
:::note
While a standard installation is recommended for most users, installing Jellyfin as a service is ideal for dedicated servers. This allows Jellyfin to start automatically at boot and remain active even when no users are logged into the system.
:::
Running as a **Network Service** is preferred over **Local System** for the principle of least privilege. Follow these steps to ensure proper access without over-provisioning permissions.
### Installing as a Service
1. In the Windows installer, select **Install as a Service**.
2. Choose the default install path, `C:\Program Files\Jellyfin\Server`.
3. Choose the default data path, `C:\ProgramData\Jellyfin\Server`.
4. Choose **Use Network Service account** for the account type.
5. Uncheck **Start Service after Install**.
6. Click **Install**.
### Configure Service Account Permissions
The service account needs access to Jellyfin's configuration files.
1. Navigate to `C:\ProgramData\`.
2. Right-click the **Jellyfin** folder, and click **Properties** > **Security** > **Advanced**.
3. Beside **Owner**, click **Change**, and enter `NETWORK SERVICE` in the text box. Click **OK**.
4. Click **Add** under Principal. Click **Select a principal** and enter `NETWORK SERVICE` in the text box. Click **OK**.
5. Under **Basic permissions** for the new principal, choose one of the following based on your security preference, then Click **OK**.
* **Modify**: Allows Jellyfin to read, write, and delete its own data without granting it the power to change system permissions.
* **Full Control**: Easiest for setup. Grants all rights, including the ability to change owner and permissions.
6. Check the option **Replace all child object permission entries...**. Click **Apply**.
7. Exit the menu.
### Configure Media Library Permissions
After setting up a media folder, you should grant the service account read & execute access to that folder to prevent "Path not found" errors.
1. Right-click your media folder, and click **Properties** > **Security** > **Advanced**.
2. Click **Add** under Principal. Click **Select a principal** and enter `NETWORK SERVICE` in the text box. Click **OK**.
3. Under **Basic permissions** for the new principal, choose based on how you want Jellyfin to interact with your files, then Click **OK**.
* **Read & execute** (Recommended): Allows Jellyfin to see and play your media. This is the safest option as it prevents the server from accidentally deleting or modifying your original movie files.
* **Modify**: Required only if you want to use `Delete` from within the Jellyfin UI, or if you want Jellyfin to save subtitles and `.nfo` metadata files directly into your movie folders.
* **Full Control**: Not recommended for media folders. This grants administrative rights that the service does not need for playback.
4. Check the option **Replace all child object permission entries...**. Click **Apply**.
5. Exit the menu.
### Verify and Initialize
1. Press **Windows**+**R** and type "services.msc". Hit **Enter**.
2. Find the **Jellyfin Server** service and verify the "Log On As" column shows **Network Service**.
3. Right-click **Jellyfin Server** service and select **Start**.
4. Navigate to http://localhost:8096 to complete the wizard.
### Troubleshooting
* **Missing ProgramData Folder:** If `C:\ProgramData\Jellyfin` does not exist yet, proceed to **Verify and Initialize** and follow steps 1 and 3. This will generate the necessary directory structure so you can then apply permissions.
* **Empty Libraries:** If the setup wizard does not "see" your media, ensure the `NETWORK SERVICE` account has at least **List folder contents** permissions on the parent directory leading to your media folder (e.g., if media is in `D:\Media\Movies`, check permissions for `D:\Media`).
* **Remote Access:** To allow other devices on your network to connect, you must add a Windows Firewall rule to allow **Inbound** traffic on TCP port `8096`. For detailed steps, see the [Networking Guide](../../post-install/networking/index.md).
+13
View File
@@ -31,6 +31,19 @@ Additionally, there are several third parties providing unofficial container ima
## Installation Instructions
:::warning
If you wish to use [Windows](/docs/general/installation/windows) or [macOS](/docs/general/installation/macos), please install Jellyfin natively instead.
While it is possible to run Jellyfin in a Container on a Windows or macOS host, it is NOT supported. Some features are known to be broken when running in a Container on platforms other than Linux, Notably:
- Hardware Accelerated Transcoding
- [Scanning on macOS in Docker](https://github.com/jellyfin/jellyfin/issues/13093)
You WILL NOT receive any support for running Jellyfin in a Container on platforms other than Linux.
:::
Replace `uid:gid` if you want to run jellyfin as a specific user/group. Exclude the `user` argument entirely if you want to use the default user.
import Tabs from '@theme/Tabs';
+14 -12
View File
@@ -8,28 +8,28 @@ sidebar_position: 3
## Debian / Ubuntu and derivatives
To simplify deployment and help automate this for as many users as possible, we provide a BASH script to handle repo installation as well as installing Jellyfin on Debian / Ubuntu and derivatives.
All you need to do is run this command on your system (requires `curl`, or subsitute `curl` with `wget -O-`):
Download and verify the script, then execute it on your system (requires `curl` and `sha256sum`):
```sh
curl https://repo.jellyfin.org/install-debuntu.sh | sudo bash
curl -s https://repo.jellyfin.org/install-debuntu.sh -O && \
curl -s https://repo.jellyfin.org/install-debuntu.sh.sha256sum -O && \
sha256sum -c install-debuntu.sh.sha256sum
```
:::note
`install-debuntu.sh: OK` means the checksum is correct.
You can verify the script download integrity with (requires `sha256sum`):
```sh
diff <( curl -s https://repo.jellyfin.org/install-debuntu.sh -o install-debuntu.sh; sha256sum install-debuntu.sh ) <( curl -s https://repo.jellyfin.org/install-debuntu.sh.sha256sum )
```
An empty output means everything is correct. Then you can inspect the script to see what it does (optional but recommended) and execute it with:
You can optionally inspect the script to see what it does before executing it:
```sh
less install-debuntu.sh
sudo bash install-debuntu.sh
```
:::
Then execute it with:
```sh
sudo bash install-debuntu.sh
```
:::note
@@ -37,6 +37,8 @@ The script tries to handle as many common derivatives as possible, including, at
:::
If you do not want to execute a script with superuser permissions, you can also install the Jellyfin software repository manually (using either [extrepo](/docs/general/installation/advanced/manual/#debian-using-extrepo) or the [fully manual method](/docs/general/installation/advanced/manual/#official-linux-repository-manual)).
## Other Distributions
For other distributions, [containers](/docs/general/installation/container) are the recommended way to install Jellyfin. There are also [community-maintained packages](/docs/general/installation/advanced/community) provided by 3rd parties if you would like to use them instead.
+1 -1
View File
@@ -26,4 +26,4 @@ sidebar_position: 1
1. Go to [Add or remove programs](https://support.microsoft.com/en-us/windows/uninstall-or-remove-apps-and-programs-in-windows-4b55f974-2cc6-2d2b-d092-5905080eaf98) in Windows settings.
2. Search for Jellyfin.
3. Click Uninstall.
3. Click Uninstall.
@@ -30,13 +30,13 @@ Cons:
Setup on server:
1. Install the Tailscale app on the client device. Instructions are available in [Tailscale's official install guide](https://tailscale.com/kb/1347/installation)
2. Login to the Tailscale client and connect to the tailnet. On Windows and macOS that can be done through the icon in the system tray. On Linux that can be done with the comnand `sudo tailscale up`
2. Login to the Tailscale client and connect to the tailnet. On Windows and macOS that can be done through the icon in the system tray. On Linux that can be done with the command `sudo tailscale up`
3. Find and note your Tailscale IP of the server according to the [Tailscale Documentation](https://tailscale.com/kb/1033/ip-and-dns-addresses?tab=linux#finding-your-tailscale-ip-address). This IP will be used for other devices to connect. The IP should start with 100 (e.g. 100.12.34.56).
Setup on clients:
1. Install the Tailscale app on the client device. Instructions are available in [Tailscale's official install guide](https://tailscale.com/kb/1347/installation)
2. Login to the Tailscale client and connect to the tailnet. On Windows and macOS that can be done through the icon in the system tray. On Linux that can be done with the comnand `sudo tailscale up`. On mobile devices that can be done through the tailscale app.
2. Login to the Tailscale client and connect to the tailnet. On Windows and macOS that can be done through the icon in the system tray. On Linux that can be done with the command `sudo tailscale up`. On mobile devices that can be done through the tailscale app.
3. Type in the server IP from above into your browser or Jellyfin client of choice and connect. (e.g. 100.12.34.56:8096)
## Using Tailscale with a reverse proxy
@@ -52,7 +52,7 @@ Setup on Jellyfin server:
Setup on reverse proxy server:
1. Install the Tailscale app on the client device. Instructions are available in [Tailscale's official install guide](https://tailscale.com/kb/1347/installation)
2. Login to the tailscale client and connect to the tailnet. On Linux this can be done with the comnand `sudo tailscale up`
2. Login to the tailscale client and connect to the tailnet. On Linux this can be done with the command `sudo tailscale up`
3. Setup a reverse proxy of your choice and set the upstream server to the IP from above. Example [Caddy](./reverse-proxy/caddy) configuration: (Assuming server has Tailscale IP of 100.12.34.56)
```txt
@@ -4,7 +4,10 @@ title: Caddy
sidebar-position: 1
---
> **Note:** For HTTP/3 support, ensure UDP port 443 is forwarded/opened on your firewall, as HTTP/3 uses UDP.
:::note
For HTTP/3 support, ensure UDP port 443 is forwarded/opened on your firewall, as HTTP/3 uses UDP.
:::
"[Caddy](https://caddyserver.com/), sometimes clarified as the Caddy web server, is an open source, HTTP/2-enabled web server written in Go. It uses the Go standard library for its HTTP functionality." - [Wikipedia](<https://en.wikipedia.org/wiki/Caddy_(web_server)>)
@@ -15,6 +18,7 @@ You can reverse proxy to Jellyfin either with or without a config file, and eith
If you aren't familiar with Caddy yet, check out its [Getting Started](https://caddyserver.com/docs/getting-started) guide.
:::caution
There are a some guides that have a Caddyfile which includes a `tls` section with the DNS provider's API key as shown in the following example.
```Caddyfile
@@ -42,18 +46,12 @@ Please read the [Let's Encrypt documentation](https://letsencrypt.org/docs/chall
The easiest way to reverse proxy to Jellyfin is with the `reverse-proxy` command:
```bash
caddy reverse-proxy --from :5001 --to 127.0.0.1:8096
```
That is a simple but production-ready plaintext HTTP reverse proxy.
If you have:
- permission to bind to low ports, and
- a public domain name's DNS records pointed at your machine,
then you can serve over HTTPS just as easily:
then you can serve over HTTPS easily:
```bash
caddy reverse-proxy --from example.com --to 127.0.0.1:8096
@@ -64,15 +62,7 @@ You will see Caddy provision a TLS certificate for your site and if it succeeds,
### Caddyfile
If you want to use a config file, create a file called `Caddyfile` for the configuration.
The first `reverse-proxy` command above is equivalent to the following options.
```txt
:5001
reverse_proxy 127.0.0.1:8096
```
To get HTTPS, simply change the first line to your domain name.
The following config is equivalent to the command above.
```txt
example.com
@@ -27,7 +27,7 @@ When traffic is forwarded through a reverse proxy, Jellyfin sees the proxys I
This introduces potential security risks and can also break compatibility, since Jellyfin will not be able to differentiate between local and remote connections.
Therefore, if set up incorrectly, all limitations for external access will not work.
Therefore, the IP address(es) of your reverse proxy must be configured under “Known Proxies” in Jellyfins **Network** settings.
Therefore, **the IP address(es) of your reverse proxy must be configured under “Known Proxies”** in Jellyfins Network settings.
This allows Jellyfin to respect the `X-Forwarded-For`, `X-Forwarded-Proto`, and `X-Forwarded-Host` headers and use the associated value as the source IP address. By default, Jellyfin will discard all forwarded-for headers that do not originate from a "known Proxy". This is so that malicious devices will not be able to hide their IP address by providing a forwarded-for header.
This assumes that the reverse proxy is set up to include this header, which is not always the case by default.
@@ -207,7 +207,7 @@ TOML files can't support environment variables, so all values must be hard coded
email = "YOU@DOMAIN_NAME"
storage = "acme.json"
# Use HTTP-01 ACME challenge
#[certificateresolvers.leresolver.acme.httpChallenge]
#[certificatesresolvers.leresolver.acme.httpChallenge]
# entryPoint = "http"
# Use a DNS-01 ACME challenge rather than HTTP-01 challenge.
# Mandatory for wildcard certificate generation.
@@ -13,6 +13,7 @@ Jellyfin produces logs that can be monitored by Fail2ban to prevent brute-force
- Jellyfin remotely accessible
- Fail2ban installed and running
- Knowing where the logs for Jellyfin are stored: by default `/var/log/jellyfin/` for desktop and `/config/log/` for docker containers.
- Jellyfin log level set to `Info` (failed authentication entries are not logged at `Error`). This setting is can be found in `logging.json`
## Step one: create the jail
@@ -35,11 +36,53 @@ filter = jellyfin
maxretry = 3
bantime = 86400
findtime = 43200
logpath = /path_to_logs/jellyfin*.log
logpath = /path_to_logs/log_*.log
```
Save and exit nano.
Jellyfin rotates logs daily and `fail2ban` cannot detect the newly created log files without service restart or config reload.
To fix this you need a daily timer that `reloads` above fail2ban jellyfin jail whenever the logs are rotated at roughly around midnight.
```bash
sudoedit /etc/systemd/system/fail2ban-jellyfin-reload.timer
```
Add this to the new file:
```bash
[Unit]
Description=Reload Fail2Ban jellyfin jail daily
[Timer]
OnCalendar=*-*-* 00:45:00
Persistent=true
[Install]
WantedBy=timers.target
```
Save and exit nano.
```bash
sudoedit /etc/systemd/system/fail2ban-jellyfin-reload.service
```
Add this to the new file:
```bash
[Unit]
Description=Reload Fail2Ban jellyfin jail
[Service]
Type=oneshot
ExecStart=/usr/bin/fail2ban-client reload jellyfin
```
Save and exit nano.
Enable and start the service:
```bash
sudo systemctl enable --now fail2ban-jellyfin-reload.timer
```
Note:
1. If Jellyfin is running in a docker container, add the following to the `jellyfin.local` file:
@@ -82,7 +125,7 @@ sudo systemctl status fail2ban
Assuming you've at least one failed authentication attempt, you can test this new jail with `fail2ban-regex`:
```bash
sudo fail2ban-regex /path_to_logs/*.log /etc/fail2ban/filter.d/jellyfin.conf --print-all-matched
sudo fail2ban-regex /path_to_logs/log_*.log /etc/fail2ban/filter.d/jellyfin.conf --print-all-matched
```
---
@@ -150,7 +193,7 @@ Replace `<upstream-server-ip>` with the actual IP address of your upstream serve
iptables -C INPUT -j f2b-<name> 2>/dev/null || iptables -I INPUT -j f2b-<name>; \
iptables -I f2b-<name> 1 -s <ip> -j DROP' && \
echo "Banned <ip> from jail <name> via upstream proxy" >> /var/log/fail2ban.log
# Option: actionunban
# 1. Remove the banned IP from the dynamic chain
# 2. Remove the chain if it becomes empty (cleanup)
@@ -165,7 +208,7 @@ Replace `<upstream-server-ip>` with the actual IP address of your upstream serve
echo "Unbanned <ip> from jail <name> via upstream proxy and cleaned up chain if empty" >> /var/log/fail2ban.log
```
After making chaneges, save and close the file.
After making changes, save and close the file.
2. **Update Fail2Ban Jails to Use the Dynamic Chain Action**:
@@ -195,7 +238,7 @@ Replace `<upstream-server-ip>` with the actual IP address of your upstream serve
action = proxy-iptables-dynamic
```
After making chaneges, save and close the file.
After making changes, save and close the file.
### Step three: Add proxy IPs to Jellyfin
@@ -211,7 +254,7 @@ Replace `<upstream-server-ip>` with the actual IP address of your upstream serve
Open your Jellyfin server's dashboard, go to `Advanced` -> `Networking`, and then scroll down to `Known proxies`.
Enter your comma-seperated list of proxy IP ranges. You'll need to reboot the Jellyfin server as indicated.
Enter your comma-separated list of proxy IP ranges. You'll need to reboot the Jellyfin server as indicated.
### Step four: Restart Fail2Ban and Test the Setup
@@ -257,7 +300,7 @@ Replace `<upstream-server-ip>` with the actual IP address of your upstream serve
6. **Verify Unban**:
Verify that the IP is removed from the corresponding jail's chain ('f2b-jail-name'):
Verify that the IP is removed from the corresponding jail's chain ('f2b-jail-name'):
```bash
ssh root@<upstream-server-ip> "iptables -L f2b-jellyfin"
+35 -22
View File
@@ -16,24 +16,24 @@ Neither does Jellyfin require an internet connection to run; however you should
This section aims to provide an administrator with knowledge on what ports Jellyfin binds to and what purpose they serve.
| Port | Protocol | Configurable | Description |
|---|---|---|---|
| 8096 | TCP | ✔️ | Default HTTP |
| 8920 | TCP | ✔️ | Default HTTPS |
| 7359 | UDP | ❌ | Client Discovery |
| Port | Protocol | Configurable | Description |
| ---- | -------- | ------------ | ---------------- |
| 8096 | TCP | ✔️ | Default HTTP |
| 8920 | TCP | ✔️ | Default HTTPS |
| 7359 | UDP | ❌ | Client Discovery |
<details>
<summary>See details</summary>
- **HTTP Traffic** (8096/TCP):
The web frontend can be accessed here. You can modify this setting from the **Networking** page in the admin settings.
The web frontend can be accessed here. You can modify this setting from the **Networking** page in the admin settings.
- **HTTPS Traffic** (8920/TCP):
Used when https is enabled. By default this port will not be used.
This setting can also be modified from the **Networking** page to use a different port.
Used when https is enabled. By default this port will not be used.
This setting can also be modified from the **Networking** page to use a different port.
- **Client Discovery** (7359/UDP):
Allows clients to discover Jellyfin on the local network. A broadcast message to this port will return detailed information about your server that includes name, ip-address and ID.
Allows clients to discover Jellyfin on the local network. A broadcast message to this port will return detailed information about your server that includes name, ip-address and ID.
</details>
@@ -43,20 +43,33 @@ This section focusses on how to make Jellyfin Available within Networks.
Here you will find descriptions on how to make Jellyfin accessible both only locally and through the Internet.
In general, Jellyfin will be available locally on the specified port over the host-ip - e.g. `http://10.0.0.2:8096`.
However its also possible to create a local DNS entry that will point to your Jellyfin-Server - e.g. `http://jellyfin.local:8096`.
However its also possible to create a local DNS entry that will point to your Jellyfin-Server - e.g. `http://jellyfin.internal:8096`.
<details>
<summary>Learn more about limitations with local DNS</summary>
Devices like Google Chromecast or Google Streamer use hardcoded DNS Servers - therefore they will not make use of your local DNS entries.
There are multiple workarounds for this issue.
Devices like Google Chromecast or Google TV Streamer may ignore the DNS server provided by your local network.
As a result, they may not resolve custom local DNS entries correctly.
The easiest involves the usage of IPv6 Entries in the public DNS.
Since IPv6 addresses do not differentiate between local and public, the address will be abled to be resolved locally.
This, however, requires the use of a public DNS server - The Jellyfin Server does not have to be accessible from the outside though!
One option to work around this is to publish an IPv6 DNS record through a public DNS provider.
If your Jellyfin server has a globally routable IPv6 address, devices can resolve it without relying on your local DNS server.
The server itself does not need to be publicly accessible. Inbound access can still be restricted through your firewall.
</details>
### Allowing Access
Jellyfin provides flexible access control options. External access can either be completely disabled or selectively enabled for individual users.
For these controls to function correctly, Jellyfin must know which IP ranges should be considered part of the local network.
These ranges can be configured under `Networking` -> `Local Networks` using comma-separated CIDR notation entries.
Global external access settings can be configured under `Networking` -> `Remote Access Settings`.
User-specific external access permissions can be configured under `Users` -> `Edit User` -> `Allow remote connections to this server`.
External access settings through a reverse proxy will only work if [known proxies](./8_reverse-proxy/index.md#forwarded-for-headers) are set up correctly!
Ensure that the configured access permissions align with the network scope defined in the local network settings.
### Firewall / Port Forwarding
Networks are usually divided from each other by firewalls. These block all incoming traffic and are meant to protect the network.
@@ -67,18 +80,18 @@ Opening a port directly to the Internet is therefore insecure and not recommende
There are different layers where a firewall can be placed:
| Layer | Example | Description |
| --- | --- | --- |
| Local | Docker, VM | Open ports at this layer to allow traffic from the Host to enter the Application |
| Host | physical machine, operating system | Open ports at this layer to allow traffic from the Network to enter the Host device |
| Network | Router | Open ports at this layer to allow traffic from the Internet to enter the Local Network |
| Layer | Example | Description |
| ------- | ---------------------------------- | -------------------------------------------------------------------------------------- |
| Local | Docker, VM | Open ports at this layer to allow traffic from the Host to enter the Application |
| Host | physical machine, operating system | Open ports at this layer to allow traffic from the Network to enter the Host device |
| Network | Router | Open ports at this layer to allow traffic from the Internet to enter the Local Network |
<details>
<summary>Port forwarding vs. opening a Port</summary>
Whilst Routers often allow you to forward a port, firewalls typically only allow you to open one.
The difference is within the Target. Opening a Port essentially just means that traffic on this Port will go through.
Forwarding a Port you typically do in NAT scenarios - traffic is coming in on your public IP Address, what device inside your network should recieve it.
Forwarding a Port you typically do in NAT scenarios - traffic is coming in on your public IP Address, what device inside your network should receive it.
Sometimes, port forwarding also lets you map an external port to a different internal port.
</details>
@@ -100,7 +113,7 @@ Here is linked below how to open ports for:
Since Jellyfin is entirely self-hosted, you must manually expose it to the internet.
To do so, you need a method to access the HTTP(S) ports remotely.
Automatic discovery only works locally and should not be exposed externally
Automatic discovery only works locally and should not be exposed externally.
To access a server remotely there will need to be a way to find it or its network on the internet.
This can be done through the public IP Address of the Device or for IPv6 the Server's directly.
+6 -3
View File
@@ -23,8 +23,7 @@ Set up an administrator account for managing the server. Choose a strong passwor
Add media libraries at this page. Click on the + to add a library. Alternatively, click on "Next" without adding anything to skip this step and add media later.
![Setup Wizard Add Media Library Page](/images/docs/post-install/setup-wizard/setup-wizard-3-media-main.png)
In the popup, chose a type on the "Content Type" dropdown, and set a display name in the "Display Name" field. Then, add some folders using the + button. If you don't see your media folders listed, you might have permission issues. You can get help on our [forum](https://forum.jellyfin.org/) or [chat rooms](/contact)
Read more about media libraries at the [media libraries' documentation](/docs/general/server/libraries/)
In the popup, chose a type on the "Content Type" dropdown, and set a display name in the "Display Name" field. Then, add some folders using the + button. If you don't see your media folders listed, you might have permission issues. You can get help on our [forum](https://forum.jellyfin.org/) or [chat rooms](/contact). Read more about media libraries at the [media libraries' documentation](/docs/general/server/libraries/).
![Setup Wizard Add Media Library Popup](/images/docs/post-install/setup-wizard/setup-wizard-4-media-popup.png)
## Set a Preferred Metadata Language
@@ -34,7 +33,11 @@ Select a preferred language and region for metadata fetching as the server-wide
## Networking Settings
Some basic options for networking can be set on this page. For most users, it is recommended to **enable** the "Allow remote access to this server" option, and **disable** the "Enable automatic port mapping" option.
Some basic networking options can be configured on this page. For most users, it is recommended to **enable** the "Allow remote access to this server" option.
Detailed information about remote access configuration can be found in our dedicated [Networking Guide](./networking/index.md#allowing-access).
Since "automatic port mapping" relies on UPnP, a protocol commonly associated with security concerns, it is recommended to **disable** this option unless it is specifically required.
![Setup Wizard Networking Page](/images/docs/post-install/setup-wizard/setup-wizard-6-networking.png)
## Next Steps
@@ -38,13 +38,11 @@ Hardware accelerated HDR/DV to SDR tone-mapping is supported on **all AMD GPUs t
There are two different methods that can be used on Windows and/or Linux. Pros and cons are listed below:
1. **OpenCL**
- Pros - Supports Dolby Vision P5, detailed fine-tuning options, widely supported hardware.
- Cons - Zero-copy is not supported on Linux.
2. **Vulkan**
- Pros - Supports Dolby Vision P5, libplacebo renderer, ROCm OpenCL runtime is not required.
- Cons - Linux only, zero-copy only supports Polaris+ GPUs.
@@ -113,7 +111,7 @@ Encoding speed and quality:
## Windows Setups
Windows 10 64-bit and newer is recommeded. **AMF is not available in Windows Docker and WSL/WSL2.**
Windows 10 64-bit and newer is recommended. **AMF is not available in Windows Docker and WSL/WSL2.**
### Known Issues And Limitations On Windows
@@ -126,7 +124,6 @@ Please refer to [this section](./known-issues.md#amd-on-windows) for known issue
2. Clean install the latest driver from [AMD Drivers and Support](https://www.amd.com/en/support).
3. Don't allow the GPU to be preempted by the Windows Remote desktop session.
- Type `gpedit.msc` in Win+R shortcut key dialog and run to open the "Local Group Policy Editor".
- Navigate in the left tree **[Computer Configuration > Administrative Templates > Windows Components]**
@@ -154,7 +151,6 @@ Please refer to [this section](./known-issues.md#amd-on-windows) for known issue
Duplicate engine names indicate the GPU may have multiple video engines.
:::
- **3D** - 2D/3D engine or GPGPU workload
- **Copy** - Blitter/Copy engine workload
@@ -311,7 +307,6 @@ Root permission is required.
```
2. User mode Mesa drivers are required to be manually installed for VA-API and RADV Vulkan:
- [libva-mesa-driver](https://archlinux.org/packages/extra/x86_64/libva-mesa-driver/)
- [vulkan-radeon](https://archlinux.org/packages/extra/x86_64/vulkan-radeon/)
@@ -404,7 +399,6 @@ Root permission is required.
```
2. Use Docker command line **or** docker compose:
- Example command line:
```shell
@@ -486,7 +480,6 @@ Root permission is required.
:::
1. Install the `radeontop` package. The name varies between distros.
- On Debian & Ubuntu:
```shell
@@ -99,13 +99,13 @@ lshw -C display
See the table below to pick the best hardware acceleration method for your hardware:
| GPU Vendor | Windows | macOS | Linux |
| ---------- | ------------------------------------------ | -------------------------- | -------------------------------------- |
| GPU Vendor | Windows | macOS | Linux |
| ---------- | --------------------------------------------- | -------------------------- | ----------------------------------------- |
| AMD | [AMF (Windows)](./amd.md#windows-setups) | [VideoToolbox](./apple.md) | [VAAPI (AMD)](./amd.md#linux-setups) |
| Apple | N/A | [VideoToolbox](./apple.md) | N/A |
| Apple | N/A | [VideoToolbox](./apple.md) | N/A |
| Intel | [QSV (Windows)](./intel.md#windows-setups) | [VideoToolbox](./apple.md) | [QSV (Linux)](./intel.md#linux-setups) |
| Nvidia | [NVENC (Windows)](./nvidia.md#windows-setups) | N/A | [NVENC (Linux)](./nvidia.md#linux-setups) |
| Rockchip | N/A | N/A | [RKMPP](./rockchip.md) |
| Rockchip | N/A | N/A | [RKMPP](./rockchip.md) |
## Remote Hardware Acceleration
@@ -127,7 +127,7 @@ Dolby Vision (P5 & P8) to SDR tone-mapping is supported in Jellyfin 10.8 and req
- Intel VPP HDR10 tone-mapping is supported on Intel QSV and VA-API on Linux.
- VPP is prefered if both tone-mapping options are enabled.
- VPP is preferred if both tone-mapping options are enabled.
- Rockchip RKMPP does support Dolby Vision tone-mapping Jellyfin 10.11 and later versions.
@@ -54,13 +54,11 @@ Hardware accelerated HDR/DV to SDR tone-mapping is supported on **all Intel GPUs
There are two different methods that can be used on Windows and/or Linux. Pros and cons are listed below:
1. **OpenCL**
- Pros - Supports Dolby Vision P5, detailed fine-tuning options, widely supported hardware.
- Cons - The OpenCL runtime sometimes need to be manually installed on Linux.
2. **QSV VPP**
- Pros - Lower power consumption, realized by Intel fixed-function LUT hardware.
- Cons - Poor tuning options, limited supported GPU models, **currently only available on Linux**.
@@ -205,7 +203,7 @@ You only need to follow the [Windows Setups](./intel.md#windows-setups) and [Lin
## Windows Setups
Windows 10 64-bit and newer is recommeded. **QSV is not available on Windows Docker and WSL/WSL2.**
Windows 10 64-bit and newer is recommended. **QSV is not available on Windows Docker and WSL/WSL2.**
### Known Issues And Limitations On Windows
@@ -218,7 +216,6 @@ Please refer to [this section](/docs/general/post-install/transcoding/hardware-a
2. Clean install the latest EXE or INF driver from [Intel download center](https://www.intel.com/content/www/us/en/download-center/home.html).
3. Don't allow the GPU to be preempted by the Windows Remote desktop session.
- Type `gpedit.msc` in Win+R shortcut key dialog and run to open the "Local Group Policy Editor".
- Navigate in the left tree **[Computer Configuration > Administrative Templates > Windows Components]**
@@ -246,7 +243,6 @@ Please refer to [this section](/docs/general/post-install/transcoding/hardware-a
Duplicate engine names indicate the GPU may have multiple MFX video engines.
:::
- **3D** - 2D/3D engine, QSV VPP or GPGPU workload
- **Copy** - Blitter/Copy engine workload
@@ -349,7 +345,6 @@ Root permission is required.
7. Check the supported QSV / VA-API codecs:
:::note
- `iHD driver` indicates support for the QSV and VA-API interfaces.
- `i965 driver` indicates only support for the VA-API interface, which should only be used on pre-Broadwell platforms.
@@ -407,7 +402,6 @@ Root permission is required.
```
2. User mode Intel media drivers and the OpenCL runtime are required to be manually installed for enabling QSV / VA-API:
- [intel-media-driver](https://archlinux.org/packages/extra/x86_64/intel-media-driver/)
- [intel-media-sdk](https://archlinux.org/packages/extra/x86_64/intel-media-sdk/)
@@ -496,7 +490,6 @@ What you need to do is pass the host's `render` group id to Docker and modify th
```
2. Use docker command line **or** docker compose:
- Example command line:
```shell
@@ -565,7 +558,7 @@ This follows the same principles as for the Docker, with one small change that y
The devices in Kubernetes are added as host path mounts, they are not separated into separate volumes like in the Docker example.
1. Example Kubernetes (API version 1) configuraton file written in YAML:
1. Example Kubernetes (API version 1) configuration file written in YAML:
```yaml
# Example of an incomplete deployment spec
@@ -635,7 +628,7 @@ This has been tested with LXC 3.0 and may or may not work with older versions.
lxc config device add <CONTAINER_NAME> gpu gpu gid=<GID_OF_HOST_RENDER_GROUP>
```
4. Make sure you have the requied devices within the container:
4. Make sure you have the required devices within the container:
```shell
$ lxc exec jellyfin -- ls -l /dev/dri
@@ -668,7 +661,6 @@ This has been tested with LXC 3.0 and may or may not work with older versions.
**Proxmox VE 7 or Older**:
:::note
- Jellyfin needs to run in a **privileged** LXC container.
- An existing unprivileged container can be converted to a privileged container by taking a backup and restoring it as privileged.
@@ -706,7 +698,6 @@ Root permission is required.
:::
1. Install the `intel-gpu-tools` package **on the host system**, which is used for debugging Intel graphics driver on Linux. The name varies between distros.
- On Debian & Ubuntu:
```shell
@@ -728,7 +719,6 @@ Root permission is required.
Duplicate engine names indicate the GPU may have multiple MFX video engines.
:::
- **Render/3D** - 2D/3D engine, QSV VPP or GPGPU workload
- **Blitter** - Blitter/Copy engine workload
@@ -816,9 +806,13 @@ Root permission is required.
:::
1. Install the latest linux firmware packages **on the host system**. The name varies between distros.
- On Debian:
```shell
sudo apt update && sudo apt install -y firmware-intel-graphics
```
Or, if you're on an older debian version :
```shell
sudo apt update && sudo apt install -y firmware-linux-nonfree
```
@@ -845,7 +839,6 @@ Root permission is required.
```
2. Add the required i915 kernel parameter on the host system to enable loading GuC and HuC firmware:
- Check the kernel module in use, goto step 3 if **xe** kernel driver is in use.
:::note
@@ -879,7 +872,6 @@ Root permission is required.
```
3. Update the initramfs and grub. The commands varies between distros.
- On Debian & Ubuntu:
```shell
@@ -16,7 +16,6 @@ This page lists all known issues and limitations of hardware acceleration with J
1. Some Linux distros intentionally disabled the H.264 and HEVC codecs from the Mesa VA-API driver.
Known affected distros:
- [Fedora](https://www.phoronix.com/news/Fedora-Disable-Bad-VA-API)
- [OpenSUSE](https://www.webpronews.com/fedora-and-opensuse-disable-gpu-accelerated-video-over-patent-concerns/)
@@ -40,11 +39,9 @@ This page lists all known issues and limitations of hardware acceleration with J
## Intel on Linux
1. Intel Gen 11 [**Jasper Lake**](https://ark.intel.com/content/www/us/en/ark/products/codename/128823/products-formerly-jasper-lake.html) and [**Elkhart Lake**](https://ark.intel.com/content/www/us/en/ark/products/codename/128825/products-formerly-elkhart-lake.html) platforms (e.g. N5095, N5105, N6005, J6412) have quirks when using video encoders on Linux. The [Low-Power Encoding](./intel.md#low-power-encoding) mode MUST be configured and enabled for correct VBR and CBR bitrate control that is required by Jellyfin.
- Ticket: [https://gitlab.freedesktop.org/drm/intel/-/issues/8080](https://gitlab.freedesktop.org/drm/intel/-/issues/8080)
2. The default kernel 5.15 that comes with Ubuntu 22.04 LTS has a regression on Intel Gen 11 graphics (ICL, JSL and EHL) that prevents you from using the Low-Power encoding mode. Linux 5.16+ is not affected.
- Ticket: [https://gitlab.freedesktop.org/drm/intel/-/issues/4067](https://gitlab.freedesktop.org/drm/intel/-/issues/4067)
- Fixed by: [drm/i915/gen11: Moving WAs to icl_gt_workarounds_init()](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=52255ef662a5d490678fbad64a735f88fcba564d)
@@ -58,7 +55,6 @@ This page lists all known issues and limitations of hardware acceleration with J
This will move you off a 5.15 kernel which could have other implications. If it breaks something you can return to the normal kernel by installing the linux-generic package.
3. The kernel range from 5.18 to 6.1.3 have an issue that locks up and resets the i915 kernel driver when using OpenCL based HDR/DV tone-mapping. Linux 5.18-, 6.0.18+, 6.1.4+ are not affected.
- Ticket: [https://gitlab.freedesktop.org/drm/intel/-/issues/7627](https://gitlab.freedesktop.org/drm/intel/-/issues/7627)
- Fixed by: [drm/i915: improve the catch-all evict to handle lock contention](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3f882f2d4f689627c1566c2c92087bc3ff734953)
@@ -80,7 +76,6 @@ This page lists all known issues and limitations of hardware acceleration with J
11. The kernel support for Intel Gen 13 (or Gen 20?) LNL and BMG / ARC B-series are incomplete before Linux 6.12.
12. The LTS kernel range 6.6.26 - 6.6.32 and the stable kernel range 6.8.5 - 6.9.3 have i915 driver bugs, which may cause problems on Intel Gen 12.5 DG2 / ARC A-series GPUs. If you are affected, please upgrade to kernel 6.6.33+ (LTS) or 6.9.4+. Ubuntu 24.04 with kernel versions 6.8.0-38 thru 6.8.0-41 are also affected by this issue. Upgrade to Ubuntu kernel 6.8.0-44+ if you are on the affected kernels.
- Issue: [https://github.com/jellyfin/jellyfin/issues/11380](https://github.com/jellyfin/jellyfin/issues/11380)
- Ubuntu bug: [https://bugs.launchpad.net/ubuntu/+source/linux/+bug/2072755](https://bugs.launchpad.net/ubuntu/+source/linux/+bug/2072755)
@@ -88,17 +83,18 @@ This page lists all known issues and limitations of hardware acceleration with J
14. Resizable-BAR is mandatory for hardware acceleration on BMG / ARC B-series cards, or the [media driver will crash the transcoder](https://github.com/intel/media-driver/issues/1893).
15. Intel Compute-Runtime currently uses LLVM 14 for compilation [as seen on the Intel bug report page](https://github.com/intel/intel-graphics-compiler/issues/289), making it unavailable in some distibutions like Debian Trixie [as seen on the Debian bug report page](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1072376). Intel provided releases [on the Intel GitHub page](https://github.com/intel/compute-runtime/releases) which only require matching a matching libc runtime may be used instead.
15. Intel Compute-Runtime currently uses LLVM 14 for compilation [as seen on the Intel bug report page](https://github.com/intel/intel-graphics-compiler/issues/289), making it unavailable in some distributions like Debian Trixie [as seen on the Debian bug report page](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1072376). Intel provided releases [on the Intel GitHub page](https://github.com/intel/compute-runtime/releases) which only require matching a matching libc runtime may be used instead.
## Nvidia
1. Consumer targeted [Geforce and some entry-level Quadro](https://developer.nvidia.com/video-encode-and-decode-gpu-support-matrix-new) cards have an artificial limit on the number of concurrent NVENC encoding sessions. This restriction can be circumvented by applying an [unofficial patch](https://github.com/keylase/nvidia-patch) to the NVIDIA Linux and Windows driver.
1. Consumer targeted [Geforce and some entry-level Quadro](https://developer.nvidia.com/video-encode-decode-support-matrix) cards have an artificial limit on the number of concurrent NVENC encoding sessions. This restriction can be circumvented by applying an [unofficial patch](https://github.com/keylase/nvidia-patch) to the NVIDIA Linux and Windows driver.
| NVIDIA driver | NVENC concurrent sessions |
| ------------- | ------------------------- |
| 550 and newer | Up to 8 encoding sessions |
| 530 to 546 | Up to 5 encoding sessions |
| pre-530 | Up to 3 encoding sessions |
| NVIDIA driver | NVENC concurrent sessions |
| ------------- | -------------------------- |
| 590 and newer | Up to 12 encoding sessions |
| 550 to 58x | Up to 8 encoding sessions |
| 530 to 546 | Up to 5 encoding sessions |
| pre-530 | Up to 3 encoding sessions |
2. When using Nvidia GPUs in containers (e.g. Docker, LXC), the container might randomly lose access to the GPU. A few potential workarounds can be found below:
- [https://github.com/NVIDIA/nvidia-container-toolkit/issues/48](https://github.com/NVIDIA/nvidia-container-toolkit/issues/48)
@@ -106,4 +102,4 @@ This page lists all known issues and limitations of hardware acceleration with J
- [https://github.com/ollama/ollama/issues/6928#issuecomment-2586208913](https://github.com/ollama/ollama/issues/6928#issuecomment-2586208913)
3. Docker desktop isn't supported by Nvidia Container Toolkit.
- [https://github.com/NVIDIA/nvidia-container-toolkit/issues/219#issuecomment-1903941381](https://github.com/NVIDIA/nvidia-container-toolkit/issues/219#issuecomment-1903941381)
If you need a GUI, use the docker package and podman, or similar.
If you need a GUI, use the docker package and podman, or similar.
@@ -45,7 +45,7 @@ Most NVIDIA GPUs come with NVENC/NVDEC support but **some low-end and mobile mod
:::
Video codec support can be checked via the [NVIDIA GPU Codec Support Matrix](https://developer.nvidia.com/video-encode-and-decode-gpu-support-matrix-new) prior to buying a GPU suitable for hardware acceleration.
Video codec support can be checked via the [NVIDIA GPU Codec Support Matrix](https://developer.nvidia.com/video-encode-decode-support-matrix) prior to buying a GPU suitable for hardware acceleration.
### Transcode H.264
@@ -53,6 +53,8 @@ AVC / H.264 8-bit is still widely used due to its excellent compatibility. All N
- **Decoding & Encoding H.264 8-bit** - Any NVIDIA GPU supporting NVENC/NVDEC
- **Decoding & Encoding H.264 10-bit** - Blackwell and newer (WIP, it's not currently enabled in Jellyfin)
### Transcode HEVC
HEVC / H.265 remains the first choice for storing 4K 10-bit, HDR and Dolby Vision video. It has mature software encoding support thanks to [x265](https://x265.readthedocs.io/en/master/), as well as the widely implemented hardware encoding support in most GPUs released after 2016.
@@ -67,7 +69,7 @@ Maxwell+ GPUs provide support for HEVC:
:::note
Note that in Maxwell 2nd Gen series only the GM206 variants provide HEVC 10-bit decoding support. Its sucessor Pascal has full support for HEVC 10-bit and improved speed and quality.
Note that in Maxwell 2nd Gen series only the GM206 variants provide HEVC 10-bit decoding support. Its successor Pascal has full support for HEVC 10-bit and improved speed and quality.
:::
@@ -85,7 +87,7 @@ NVIDIA added support for AV1 acceleration in their latest GPUs:
Please refer to these links:
- [NVIDIA GPU Codec Support Matrix](https://developer.nvidia.com/video-encode-and-decode-gpu-support-matrix-new)
- [NVIDIA GPU Codec Support Matrix](https://developer.nvidia.com/video-encode-decode-support-matrix)
- [NVIDIA Hardware Transcoding Calculator](https://www.elpamsoft.com/?p=Plex-Hardware-Transcoding)
@@ -93,9 +95,9 @@ Please refer to these links:
Encoding quality:
- H.264 & HEVC - Blackwell/Ada/Ampere/Turing > Turing TU117/Volta/Pascal > Maxwell
- H.264 & HEVC - Blackwell > Ada/Ampere/Turing > Turing TU117/Volta/Pascal > Maxwell
- AV1 - Ada Lovelace and Blackwell only
- AV1 - Blackwell > Ada Lovelace
Decoding & Encoding speed within the same generation:
@@ -113,7 +115,7 @@ NVENC/NVDEC performance tables:
## Windows Setups
Windows 10 64-bit and newer is recommeded. **In Jellyfin 10.10 the minimum required NVIDIA driver version is 522.25**.
Windows 10 64-bit and newer is recommended. **In Jellyfin 10.11 the minimum required NVIDIA driver version is 522.25**.
### Configure On Windows Host
@@ -136,7 +138,6 @@ Refer to [Configure On Linux Host](./nvidia.md#configure-on-linux-host) and [Con
2. Open the "Task Manager" and navigate to the GPU page.
3. Check the occupancy of the engines as follows.
- **3D** - 2D/3D engine or CUDA/GPGPU workload
- **Copy** - Blitter/Copy engine workload
@@ -151,7 +152,7 @@ Refer to [Configure On Linux Host](./nvidia.md#configure-on-linux-host) and [Con
## Linux Setups
A 64-bit Linux distribution is required. **In Jellyfin 10.10 the minimum required NVIDIA driver version is 520.56.06**.
A 64-bit Linux distribution is required. **In Jellyfin 10.11 the minimum required NVIDIA driver version is 520.56.06**.
### Configure On Linux Host
@@ -176,7 +177,6 @@ Root permission is required.
```
3. Install the NVIDIA proprietary driver by following these links. Then install two extra packages for NVENC and NVDEC support:
- On Debian: [https://wiki.debian.org/NvidiaGraphicsDrivers](https://wiki.debian.org/NvidiaGraphicsDrivers)
```shell
@@ -237,7 +237,6 @@ Root permission is required.
```
2. Install the NVIDIA proprietary driver by following the link. Then install an extra package for NVENC and NVDEC support:
- [https://wiki.archlinux.org/title/NVIDIA#Installation](https://wiki.archlinux.org/title/NVIDIA#Installation)
```shell
@@ -310,11 +309,9 @@ Root permission is required.
1. Install the NVIDIA proprietary driver on the host system. See above instructions.
2. Install the NVIDIA Container Toolkit on the host system by following this link:
- [https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html#installation-guide](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html#installation-guide)
- [https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html)
3. Use the Docker command line **or** docker-compose:
- Example command line:
```shell
@@ -355,7 +352,7 @@ Root permission is required.
:::note
If you encounter the upsteam issue `CUDA_ERROR_NO_DEVICE: no CUDA-capable device is detected`, pass these extra devices to the Docker:
If you encounter the upstream issue `CUDA_ERROR_NO_DEVICE: no CUDA-capable device is detected`, pass these extra devices to the Docker:
```shell
/dev/nvidia-caps:/dev/nvidia-caps
@@ -464,7 +461,7 @@ The paths of Jellyfin config and data folders in the official and LSIO Docker im
--environment=JELLYFIN_CONFIG_DIR=/etc/jellyfin
--environment=JELLYFIN_LOG_DIR=/var/log/jellyfin
--environment=JELLYFIN_CACHE_DIR=/var/cache/jellyfin
--volume=/your/path/to/data:/var/lib/jellyfin # Replace paths with actual paths on your host's filestystem
--volume=/your/path/to/data:/var/lib/jellyfin # Replace paths with actual paths on your host's filesystem
--volume=/your/path/to/config:/etc/jellyfin
--volume=/your/path/to/logs:/var/log/jellyfin
--volume=/your/path/to/cache:/var/cache/jellyfin
@@ -477,7 +474,7 @@ The paths of Jellyfin config and data folders in the official and LSIO Docker im
```sh
[Unit]
Description=jellyfin
[Container]
Image=docker.io/jellyfin/jellyfin:latest
AutoUpdate=registry
@@ -489,7 +486,7 @@ The paths of Jellyfin config and data folders in the official and LSIO Docker im
Environment=JELLYFIN_CONFIG_DIR=/etc/jellyfin
Environment=JELLYFIN_LOG_DIR=/var/log/jellyfin
Environment=JELLYFIN_CACHE_DIR=/var/cache/jellyfin
Volume=/your/path/to/data:/var/lib/jellyfin # Replace paths with actual paths on your host's filestystem
Volume=/your/path/to/data:/var/lib/jellyfin # Replace paths with actual paths on your host's filesystem
Volume=/your/path/to/config:/etc/jellyfin
Volume=/your/path/to/logs:/var/log/jellyfin
Volume=/your/path/to/cache:/var/cache/jellyfin
@@ -497,10 +494,10 @@ The paths of Jellyfin config and data folders in the official and LSIO Docker im
[Service]
# Inform systemd of additional exit status
SuccessExitStatus=0 143
[Install]
# Start by default on boot
WantedBy=default.target
WantedBy=default.target
```
5. Create the following udev rule to make sure the GPU devices are initialized before the container is started.
@@ -155,7 +155,6 @@ Root permission is required.
Only needed before using HDR tone-mapping on RK3588/3588S. This is done to ensure that the user space firmware and kernel driver versions match, otherwise OpenCL will not work properly.
:::
- For the 6.1 LTS kernel on [Ubuntu-Rockchip](https://github.com/Joshua-Riek/ubuntu-rockchip) & [Armbian](https://github.com/armbian) and the legacy 5.10 LTS kernel, install [v1.9-1-2131373](https://github.com/tsukumijima/libmali-rockchip/releases/download/v1.9-1-2131373/libmali-valhall-g610-g24p0-gbm_1.9-1_arm64.deb).
- For the 6.1 LTS kernel on other SBC **vendor-made** distros, install [v1.9-1-55611b0](https://github.com/tsukumijima/libmali-rockchip/releases/download/v1.9-1-55611b0/libmali-valhall-g610-g13p0-gbm_1.9-1_arm64.deb).
@@ -193,7 +192,7 @@ Root permission is required.
:::
1. Use Docker command line: (the extensive device names between `for...done` is used to ensure backward compatiblity)
1. Use Docker command line: (the extensive device names between `for...done` is used to ensure backward compatibility)
```shell
sudo docker run -d \
@@ -233,7 +232,7 @@ Root permission is required.
#### LXC (Linux Containers)
This setup might be useful for those, who use RK3588/3588S SoC as [Proxmox](https://www.proxmox.com/en/) host, where LXC is the official and the only supported way of doing lightweight virtualiztion with the help of system containers (LXC) vs application containers (docker). As of today Proxmox team does not support ARM platforms as hosts - and probably will never do - however successful deployments on ARM devices [are possible](https://github.com/jiangcuo/Proxmox-Port?tab=readme-ov-file).
This setup might be useful for those, who use RK3588/3588S SoC as [Proxmox](https://www.proxmox.com/en/) host, where LXC is the official and the only supported way of doing lightweight virtualization with the help of system containers (LXC) vs application containers (docker). As of today Proxmox team does not support ARM platforms as hosts - and probably will never do - however successful deployments on ARM devices [are possible](https://github.com/jiangcuo/Proxmox-Port?tab=readme-ov-file).
LXC setup idea is a bit similar to docker - you need to pass the **device files** of VPU from host to LXC and enable the **privileged mode** (see also important "_note_" below about privileged LXC containers).
@@ -251,7 +250,7 @@ LXC setup idea is a bit similar to docker - you need to pass the **device files*
device /dev/mpp_service
```
Example of the minumum requried extra (not full) container configuration to make VPU hardware accelearion working is presented below:
Example of the minimum required extra (not full) container configuration to make VPU hardware acceleration working is presented below:
```shell
lxc.mount.entry: /dev/dri dev/dri none bind,optional,create=dir
@@ -273,7 +272,6 @@ LXC setup idea is a bit similar to docker - you need to pass the **device files*
2. Install supported [jellyfin package](https://jellyfin.org/docs/general/installation/linux) into LXC container or optionally you can even use an official docker image inside LXC container.
3. Verify OpenCL runtime status as following - example is collected from LXC runtime of Ubuntu Jammy - steps are the same as docker deployments:
- _libmali user-space drivers should be installed inside LXC container, otherwise opencl=ocl@rk device won't be initialized_
```shell
@@ -37,4 +37,4 @@ There are four types of playback; three of which involve transcoding. The type b
When the source video is in HDR, it will need to be tone-mapped to SDR when transcoding, as Jellyfin currently
doesn't support HDR to HDR tone-mapping, or passing through HDR metadata. While this can be done in software, it is
very slow, and you may encounter situations where no modern consumer CPUs can transcode in real time. Therefore, a GPU
is always recommended, where even a basic Intel iGPU can handle as much load as a Ryzen 5800X for this usecase.
is always recommended, where even a basic Intel iGPU can handle as much load as a Ryzen 5800X for this use case.
@@ -100,3 +100,18 @@ The list of physical channels will be displayed. Click the pencil icon to the ri
![Step 2 of mapping channels](/images/docs/live-tv-setup-channels2.png)
The guide data will now automatically import. You can check that the data has been imported correctly by going to the 'Live TV Guide' page from the main Jellyfin web page on your server.
## Integrating TVHeadend without a plugin
It's possible to use TVHeadend with Jellyfin through as an M3U/XMLTV integrations.
This integration requires more CPU processing, and the plugin is therefore recommended.
This approach can be used as a backup when the plugin does not work.
1. Go to LiveTV, Tuner devices, and add a new M3U Tuner
2. Set the URL to point to `http://your.tvheadend.server:port/playlist/channels.m3u`
3. Press save
4. Go to LiveTV, TV Guide Data Providers, and add a new XMLTV source
5. Set the URL to point to `http://your.tvheadend.server:port/xmltv/channels`
6. Press save
Wait for the Guide data to refresh.
+21 -21
View File
@@ -61,33 +61,33 @@ Image types:
<sup>1</sup>Multiple backdrop images can be used to cycle through several over time. Simply append a number to the end of the filename directly after or after a hyphen, e.g. `backdrop-1.jpg`, `backdrop2.jpg`.
<sup>2</sup>These can be added to both video and audio content, but are not used by any client for audio conent.
<sup>2</sup>These can be added to both video and audio content, but are not used by any client for audio content.
<details>
<summary>Filenames, their respective types and supported media types</summary>
Unless otherwise noted, all filenames can be used either standalone (e.g. `logo.png`) or as a suffix (e.g. `movie-logo.png`)
| Filename | Type | Movies | Series | Season | Episode | Music | Artist |
| ------------------------ | --------- | --------------- | ------ | ------ | ------- | ----- | ------ |
| poster | Primary | ✅ <sup>2</sup> | ✅ | ✅ | | ✅ | |
| folder | Primary | ✅ <sup>2</sup> | ✅ | ✅ | | ✅ | |
| cover | Primary | ✅ <sup>2</sup> | ✅ | ✅ | | ✅ | |
| default | Primary | ✅ <sup>2</sup> | ✅ | ✅ | | ✅ | |
| movie | Primary | ✅ <sup>2</sup> | | | | | |
| show | Primary | | ✅ | | | | |
| jacket | Primary | | | | | ✅ | |
| thumb (suffix) <sup>1</sup> | Primary | | | | | | |
| backdrop | Backdrop | ✅ <sup>2</sup> | ✅ | ✅ | | ✅ | |
| fanart | Backdrop | ✅ <sup>2</sup> | ✅ | ✅ | | ✅ | |
| background | Backdrop | ✅ <sup>2</sup> | ✅ | ✅ | | ✅ | |
| art | Backdrop | ✅ <sup>2</sup> | ✅ | ✅ | | ✅ | |
| extrafanart (folder) | Backdrop | ✅ <sup>2</sup> | ✅ | ✅ | | ✅ | |
| banner | Banner | ✅ | ✅ | ✅ | | ✅ | |
| logo | Logo | ✅ <sup>2</sup> | ✅ | ✅ | | ✅ | |
| clearlogo | Logo | ✅ <sup>2</sup> | ✅ | ✅ | | ✅ | |
| landscape | Thumb | ✅ | ✅ | ✅ | | ✅ | |
| thumb | Thumb | ✅ | ✅ | ✅ | | ✅ | |
| Filename | Type | Movies | Series | Season | Episode | Music | Artist |
| --------------------------- | -------- | --------------- | ------ | ------ | ------- | ----- | ------ |
| poster | Primary | ✅ <sup>2</sup> | ✅ | ✅ | | ✅ | |
| folder | Primary | ✅ <sup>2</sup> | ✅ | ✅ | | ✅ | |
| cover | Primary | ✅ <sup>2</sup> | ✅ | ✅ | | ✅ | |
| default | Primary | ✅ <sup>2</sup> | ✅ | ✅ | | ✅ | |
| movie | Primary | ✅ <sup>2</sup> | | | | | |
| show | Primary | | ✅ | | | | |
| jacket | Primary | | | | | ✅ | |
| thumb (suffix) <sup>1</sup> | Primary | | | | | | |
| backdrop | Backdrop | ✅ <sup>2</sup> | ✅ | ✅ | | ✅ | |
| fanart | Backdrop | ✅ <sup>2</sup> | ✅ | ✅ | | ✅ | |
| background | Backdrop | ✅ <sup>2</sup> | ✅ | ✅ | | ✅ | |
| art | Backdrop | ✅ <sup>2</sup> | ✅ | ✅ | | ✅ | |
| extrafanart (folder) | Backdrop | ✅ <sup>2</sup> | ✅ | ✅ | | ✅ | |
| banner | Banner | ✅ | ✅ | ✅ | | ✅ | |
| logo | Logo | ✅ <sup>2</sup> | ✅ | ✅ | | ✅ | |
| clearlogo | Logo | ✅ <sup>2</sup> | ✅ | ✅ | | ✅ | |
| landscape | Thumb | ✅ | ✅ | ✅ | | ✅ | |
| thumb | Thumb | ✅ | ✅ | ✅ | | ✅ | |
<sup>1</sup> For example: `S01E01 Some Episode-thumb.jpg` <br />
<sup>2</sup> These file names can also be embedded in supported media containers (e.g. mkv) and will be used when the `Embedded Image Extractor` source is enabled for movies.
@@ -58,19 +58,17 @@ Supported filenames are:
- `trailer`
- `sample`
- `theme` - Audio file of the theme song
```txt
Best_Movie_Ever (2019)
├── Best_Movie_Ever (2019) - 1080P.mp4
└── theme.mp3
└── trailer.mp4
```
```txt
Awesome TV Show (2024)
├── Season 1
│ ├── Awesome TV Show (2024) S01E01 episode name.mp4
│ └── theme.flac
└── sample.mp4
```
@@ -4,7 +4,6 @@
Jellyfin fetches information about the media automatically from external metadata providers for most types of content.
Movies and shows can be named with a metadata provider ID to improve matching.
Movies and shows can be named with a metadata provider ID to improve matching.
```txt
Movie Name (year) [metadata provider id]
@@ -0,0 +1,74 @@
<!-- markdownlint-disable MD041 -->
### Theme media
Theme media gives browsing your library a more audio-visual touch by playing Theme songs and/or Theme videos in the background while you're looking at your media listings.
:::tip
For these to play, users need to enable the option in their clients. In the WebUI and WebUI-based clients this is found in the User settings under Display > Libraries > Theme songs, and Theme videos, respectively. Implementations in third-party clients may differ.
:::
In case both Theme songs and Theme videos are found and enabled, Theme videos will be preferred and Theme songs will not play.
In the WebUI and WebUI-based clients, if there are multiple Theme media found, they will be shuffled when opening the listing. This cannot be changed.
#### Songs
- theme.ext
- theme-music/\*
#### Videos
- backdrops/\*
:::tip
Just like any other media, Theme media will be transcoded when required or requested by the client. However, since transcoding can result in delay of Theme media playback, Web-standard formats like WebM (VP9/Opus) are recommended for a smooth experience, as they generally direct play.
:::
#### Example
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
<Tabs>
<TabItem value='movies' label='Movies'>
```txt
Movies
└── Best_Movie_Ever (2019)
├── backdrops
│   └── bluray-menu.ext
├── theme.ext
└── theme-music
└── awesome-soundtrack-song.ext
```
</TabItem>
<TabItem value='shows' label='Shows'>
```txt
Shows
└── Series Name (2010)
├── backdrops
│   ├── S1Intro.ext
│   └── S2Intro.ext
├── Season 01
│   ├── backdrops
│   │   └── S1Intro.ext
│   └── theme-music
│   └── S1Intro.ext
├── Season 02
│   ├── backdrops
│   │   └── S2Intro.ext
│   └── theme.ext
├── theme.ext
└── theme-music
├── intro-song.ext
└── outro-song.ext
```
</TabItem>
</Tabs>
+2 -1
View File
@@ -13,7 +13,8 @@ Books should be organized by type (Audiobooks, Books, Comics), then optionally b
Books
├── Audiobooks
│ ├── Author
│ │ ├── Book1.flac
│ │ ├── Book1
│ │ │ └── Book1.flac
│ │ └── Book2
│ │ └── Book2.mp3
│ └── Book3
+4
View File
@@ -77,6 +77,10 @@ import ExternalExtras from './\_video-external-extras.md';
<ExternalExtras />
import ThemeMedia from './\_video-theme-media.md';
<ThemeMedia />
import MetadataImages from './\_metadata-images.md';
<MetadataImages />
+4
View File
@@ -89,6 +89,10 @@ Specials can also be shown within a season if so desired. This can be helpful wh
Note that this will show them in both the `Specials` season, as well as the season specified.
import ThemeMedia from './\_video-theme-media.md';
<ThemeMedia />
import Video3D from './\_video-3d.md';
<Video3D />
+2 -2
View File
@@ -17,10 +17,10 @@ There are more official providers available in our [Plugin Catalog](/docs/genera
:::caution Notice for Users in Mainland China 中国大陆地区用户请注意
Because of external factors, certain metadata providers may not be accessable in mainland China. <br />
Because of external factors, certain metadata providers may not be accessible in mainland China. <br />
由于外部因素,部分元数据提供者在中国大陆地区可能无法访问。
Below is a list of known inaccessable providers: <br />
Below is a list of known inaccessible providers: <br />
下方为已知无法访问的提供者:
- The Movie Database (TMDb)
+49 -49
View File
@@ -37,54 +37,54 @@ It's currently not possible to disable .nfo metadata. Local metadata will always
User data importing is only possible for a single user. This user can be set in the .nfo settings.
:::
| Tag | Note |
| ------------- | --------------------------------------------------------------------------------------------------------------------- |
| name | |
| title | same as name |
| localtitle | same as name |
| dateadded | |
| originaltitle | |
| sortname | |
| criticrating | |
| sorttitle | |
| plot | |
| biography | same as plot |
| review | same as plot |
| language | |
| watched | please see the note about user data |
| playcount | please see the note about user data |
| lastplayed | please see the note about user data |
| countrycode | |
| lockedfields | |
| tagline | |
| country | |
| mpaa | |
| customrating | |
| runtime | |
| aspectratio | |
| lockdata | |
| studio | multiple tags allowed |
| director | multiple tags allowed |
| credits | multiple tags allowed |
| writer | multiple tags allowed |
| actor | multiple tags allowed |
| trailer | kodi format |
| displayorder | |
| year | |
| rating | same as customrating |
| ratings | multiple child tags allowed; name attribute of each tag will specify wheter the rating is critics or community rating |
| aired | |
| formed | |
| premiered | |
| releasedate | |
| enddate | |
| genre | multiple tags allowed. These tags will be ignored for music albums and music artists. |
| tag | multiple tags allowed |
| style | multiple tags allowed |
| fileinfo | |
| uniqueid | type attribute specifies id provider |
| thumb | please see the [section about images](#image-paths-and-urls-in-nfo-files) |
| fanart | please see the [section about images](#image-paths-and-urls-in-nfo-files) |
| Tag | Note |
| ------------- | ---------------------------------------------------------------------------------------------------------------------- |
| name | |
| title | same as name |
| localtitle | same as name |
| dateadded | |
| originaltitle | |
| sortname | |
| criticrating | |
| sorttitle | |
| plot | |
| biography | same as plot |
| review | same as plot |
| language | |
| watched | please see the note about user data |
| playcount | please see the note about user data |
| lastplayed | please see the note about user data |
| countrycode | |
| lockedfields | |
| tagline | |
| country | |
| mpaa | |
| customrating | |
| runtime | |
| aspectratio | |
| lockdata | |
| studio | multiple tags allowed |
| director | multiple tags allowed |
| credits | multiple tags allowed |
| writer | multiple tags allowed |
| actor | multiple tags allowed |
| trailer | kodi format |
| displayorder | |
| year | |
| rating | same as customrating |
| ratings | multiple child tags allowed; name attribute of each tag will specify whether the rating is critics or community rating |
| aired | |
| formed | |
| premiered | |
| releasedate | |
| enddate | |
| genre | multiple tags allowed. These tags will be ignored for music albums and music artists. |
| tag | multiple tags allowed |
| style | multiple tags allowed |
| fileinfo | |
| uniqueid | type attribute specifies id provider |
| thumb | please see the [section about images](#image-paths-and-urls-in-nfo-files) |
| fanart | please see the [section about images](#image-paths-and-urls-in-nfo-files) |
Provider id tags are supported as well if they follow the scheme: `<PROVIDER_NAME`+ `id>`.
@@ -99,7 +99,7 @@ Jellyfin can write metadata to .nfo files. To enable this option, select the "Nf
| .nfo tag | Note |
| ------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| title | |
| id | IMDb id for movies, TVDb id for tv shows, |
| id | IMDb id for movies, TVDb id for tv shows, |
| originaltitle | |
| seasonnumber | only for tv show seasons |
| showtitle | only for tv show episodes |
+16
View File
@@ -337,6 +337,22 @@ Downloads Hebrew subtitles from WizdomSubs for your media files. This plugin pro
- [GitHub](https://github.com/DeDuplicate/Jellyfin_wizdomsubs_downloader)
#### SmartCovers
Fallback cover-image provider for books, audiobooks, and PDFs. Extracts covers from files locally (EPUB, PDF, audio embedded art) and fetches from Open Library and Google Books when local extraction fails.
**Links:**
- [GitHub](https://github.com/GeiserX/smart-covers)
#### WhisperSubs
Local AI-powered subtitle generation using whisper.cpp. Generates SRT subtitles for movies and TV shows using a local Whisper model — no cloud APIs, no subscriptions.
**Links:**
- [GitHub](https://github.com/GeiserX/whisper-subs)
## Repositories
import { OfficialPluginRepositories, ThirdPartyRepositories } from '../../../../src/data/pluginRepositories';
+2 -3
View File
@@ -25,7 +25,7 @@ The objective of the guide is to configure the Jellyfin TVHeadend plugin to back
- Change parameters: Rights,Channel number range,Channel tags,DVR configurations,Streaming profiles,Connection limits
- Web interface: ✔
- Streaming: Basic,Advanced,HTSP
- Video recoder: Basic,HTSP,View all
- Video recorder: Basic,HTSP,View all
- (Optional) Comment: Comment for the user (for example: User used by Jellyfin)
- (Optional) Allowed networks: _Network address with network mask to allow_ (for example 127.0.0.1/32)
- Press Save
@@ -38,7 +38,7 @@ The objective of the guide is to configure the Jellyfin TVHeadend plugin to back
:::note
The parameters Change parameters, Streaming and Video recoder must be marked as shown. Otherwise, Jellyfin can connect to TVHeadend but problems may arise when reproducing the content.
The parameters Change parameters, Streaming and Video recorder must be marked as shown. Otherwise, Jellyfin can connect to TVHeadend but problems may arise when reproducing the content.
:::
@@ -56,7 +56,6 @@ By default the the _TVHeadend Hostname or IP Address_ section is configured by d
:::
3. Configure the channels for viewing in Jellyfin: even if Jellyfin manages to connect to TVHeadend, the guide will not be synchronized because there has to be a number assigned to the channels in TVHeadend. [Reference](https://emby.media/community/index.php?/topic/64583-no-channels-with-tvheadend-plugin/#entry642268)
- Manual mode
- Go to Configuration > Channel/EPG > Channels
- Select the channel to be changed and press Edit
+1 -1
View File
@@ -11,7 +11,7 @@ Note: If your media files are unavailable when the `Clean up collections and pla
## Default Jellyfin Tasks
Below is a list of tasks that Jellyfin runs peoridically by default:
Below is a list of tasks that Jellyfin runs periodically by default:
### Libraries
+2 -2
View File
@@ -9,7 +9,7 @@ title: Branding
The name "Jellyfin" and the primary logo (two integrated triangular shapes, a stylized "fin") are trademarks in Canada, the United States, the European Union, and China of "Jellyfin, Inc.", an Ontario, Canada-based not-for-profit corporation.
A perpetual, no cost license is hereby granted to all members of the Jellyfin organization ("team") and projects under [our GitHub account](https://github.com/jelyfin) to use the name and logo in furtherance of the Jellyfin project.
A perpetual, no cost license is hereby granted to all members of the Jellyfin organization ("team") and projects under [our GitHub account](https://github.com/jellyfin) to use the name and logo in furtherance of the Jellyfin project.
For all others, you are **not** free to use the name "Jellyfin" or our logo without the explicit permission of the [project leadership team](/docs/general/about#core-team), with the following exceptions:
@@ -37,7 +37,7 @@ As a general rule, "Jellyfin" should always be capitalized, but language, file,
- C# class and project names, including their files and directories, should use capitalized `Jellyfin` as required by the C# case standards (camelCase or PascalCase). `Jellyfin.LiveTv`, `Jellyfin.sln`
- Other code elements, where the code formatting or style requires lowercase, should use lowercase `jellyfin`. `jellyfinWebComponentsBowerPath`
- The Git repository and non-C# files inside of it should use lowercase `jellyfin` for convenience on case-sensitive filesystems. `build-jellyfin.ps1`
- The final output binary, initscrips, and package names should use lowercase `jellyfin` for similar reasons as above. `jellyfin.dll`, `jellyfin_3.5.2-1_all.deb`, `jellyfin.zip`
- The final output binary, initscripts, and package names should use lowercase `jellyfin` for similar reasons as above. `jellyfin.dll`, `jellyfin_3.5.2-1_all.deb`, `jellyfin.zip`
- Configuration directories can use either depending on operating system conventions. `/var/lib/jellyfin`, `AppData/Jellyfin`
- The logo has no strict rules for capitalization, the style is dependent on aesthetics and font choice.
+3 -3
View File
@@ -2,7 +2,7 @@ import { globalIgnores } from 'eslint/config';
import react from 'eslint-plugin-react';
import reactHooks from 'eslint-plugin-react-hooks';
import ts from 'typescript-eslint';
import jsxA11Y from 'eslint-plugin-jsx-a11y';
import jsxA11yX from 'eslint-plugin-jsx-a11y-x';
import globals from 'globals';
export default ts.config([
@@ -22,9 +22,9 @@ export default ts.config([
'**/*.json'
]),
react.configs.flat.recommended,
reactHooks.configs['recommended-latest'],
reactHooks.configs.flat.recommended,
...ts.configs.recommended,
jsxA11Y.flatConfigs.recommended,
jsxA11yX.configs.recommended,
{
languageOptions: {
globals: {
+5668 -3050
View File
File diff suppressed because it is too large Load Diff
+31 -38
View File
@@ -22,32 +22,15 @@
"test:web-urls": "node ./scripts/check-urls.mjs ./scripts/data/jellyfin-web-urls.json"
},
"dependencies": {
"@docusaurus/core": "3.9.2",
"@docusaurus/plugin-client-redirects": "3.9.2",
"@docusaurus/plugin-content-blog": "3.9.2",
"@docusaurus/plugin-content-docs": "3.9.2",
"@docusaurus/plugin-content-pages": "3.9.2",
"@docusaurus/plugin-sitemap": "3.9.2",
"@docusaurus/plugin-svgr": "3.9.2",
"@docusaurus/theme-classic": "3.9.2",
"@docusaurus/theme-mermaid": "3.9.2",
"@easyops-cn/docusaurus-search-local": "0.52.2",
"@fontsource/noto-sans": "5.2.10",
"@icons-pack/react-simple-icons": "13.8.0",
"@fontsource/noto-sans": "5.3.0",
"@icons-pack/react-simple-icons": "13.13.0",
"@img-comparison-slider/react": "8.0.2",
"@mdi/js": "7.4.47",
"@mdi/react": "1.6.1",
"@mdx-js/react": "3.1.1",
"@svgr/webpack": "8.1.0",
"clsx": "2.1.1",
"docusaurus-plugin-sass": "0.2.6",
"file-loader": "6.2.0",
"react": "18.3.1",
"react-dom": "18.3.1",
"sass": "1.97.1",
"swiper": "12.0.3",
"ua-parser-js": "2.0.7",
"url-loader": "4.1.1"
"swiper": "14.0.6",
"ua-parser-js": "2.0.10"
},
"browserslist": {
"production": [
@@ -62,27 +45,37 @@
]
},
"devDependencies": {
"@docusaurus/module-type-aliases": "3.9.2",
"@docusaurus/tsconfig": "3.9.2",
"@eslint/js": "9.39.2",
"@types/react": "18.3.27",
"@docusaurus/core": "3.10.2",
"@docusaurus/module-type-aliases": "3.10.2",
"@docusaurus/plugin-client-redirects": "3.10.2",
"@docusaurus/plugin-content-blog": "3.10.2",
"@docusaurus/plugin-content-docs": "3.10.2",
"@docusaurus/plugin-content-pages": "3.10.2",
"@docusaurus/plugin-sitemap": "3.10.2",
"@docusaurus/plugin-svgr": "3.10.2",
"@docusaurus/theme-classic": "3.10.2",
"@docusaurus/theme-mermaid": "3.10.2",
"@docusaurus/tsconfig": "3.10.2",
"@easyops-cn/docusaurus-search-local": "0.55.2",
"@eslint/js": "9.39.5",
"@types/react": "18.3.31",
"@types/react-helmet": "6.1.11",
"@types/react-router-dom": "5.3.3",
"eslint": "9.39.2",
"eslint-config-prettier": "10.1.8",
"eslint-plugin-import": "2.32.0",
"eslint-plugin-jsx-a11y": "6.10.2",
"eslint-plugin-n": "17.23.1",
"eslint-plugin-prettier": "5.5.4",
"eslint-plugin-promise": "7.2.1",
"caniuse-lite": "1.0.30001806",
"cspell": "10.0.1",
"docusaurus-plugin-sass": "0.2.6",
"eslint": "9.39.5",
"eslint-plugin-jsx-a11y-x": "0.2.0",
"eslint-plugin-react": "7.37.5",
"eslint-plugin-react-hooks": "5.2.0",
"globals": "16.5.0",
"markdownlint-cli": "0.47.0",
"eslint-plugin-react-hooks": "7.1.1",
"globals": "17.8.0",
"markdownlint-cli": "0.49.1",
"node-fetch": "3.3.2",
"prettier": "3.7.4",
"typescript": "5.9.3",
"typescript-eslint": "8.51.0",
"prettier": "3.9.6",
"react-dom": "18.3.1",
"sass": "1.102.0",
"typescript": "6.0.3",
"typescript-eslint": "8.65.0",
"typescript-plugin-css-modules": "5.2.0"
}
}
+487
View File
@@ -0,0 +1,487 @@
aabc
abled
actionban
actionunban
addrepo
airsafter
airsbefore
alac
albumartistsort
allports
alpn
analyzeduration
AniDB
AniList
anthonylavado
apiclient
apsell
archlinux
armbian
armhf
asahi
aspectratio
aspm
atsc
audiodbalbumid
audiodbartistid
audiofin
autoclean
autoremove
autoscans
avhw
avsd
banip
bantime
barebones
Battlemage
BDMV
behindthescenes
blitter
Blitter
boxset
Broadwell
buildinfo
cachedir
Caddyfile
candry
cdart
Celeron
centurylinklabs
certbot
Certbot
certificateresolvers
certificatesresolvers
certonly
cewert
CGNAT
CHACHA
Cheatsheet
chevrotin
chromecast
Chromecast
chronyd
CIFS
clearart
clearlogo
clinfo
codenames
codesign
collectionnumber
comskip
configdir
confs
countrycode
cpus
criticrating
crosstool
cuda
customrating
customresponseheaders
CUVID
datasheet
dateadded
dden
dearmor
debuntu
deinterlacing
deletedscene
DHLEVEL
dhparams
directio
DISABLEFILELOCKING
discart
displayepisode
displayorder
displayseason
distros
dists
dkanada
dlna
DNSPLUGIN
Dockerfiles
downmix
Downmix
downmixes
downmixing
dpkg
DRTG
druscoe
drwxr
DUCKDNSTOKEN
DXVA
elrc
emby
enddate
enmod
ETSI
evermeet
executionpolicy
exposedbydefault
EXTINF
EXTM
extradomains
extrafanart
extrepo
failregex
fanart
fastcgi
favorited
fdroid
fedor
ferferga
FFMPEGDIR
ffprobe
Fider
findtime
firewalld
firmware
firmwares
flac
Flathub
Flix
Floostream
focuscontainer
Fontawesome
forwardfor
Freccia
Freenode
frontpage
fsbs
ftab
fullchain
Geekbench
Geforce
geoblocking
Geoip
geolocation
getent
gifsicle
Gotify
gpedit
GPGPU
gstreamer
HDHR
Headend
healthcheck
hitsong
hmac
Homerun
hostname
hostnames
hostwebclient
hotfixes
hotio
hoverable
hsbs
hsts
htab
HTPC
HTSP
httpchallenge
httpchk
hwaccel
imdb
imdbid
initscripts
inotify
ipban
IPTV
ircs
irqs
itid
iwalton
Izzy
jeffbridges
jellyfin
JELLYFINDIR
Jellyfins
Jellyseer
jfdiscord
jftest
jimdogx
joshuaboniface
journalctl
jpegd
jpege
Kaby
keyrings
keyserver
Kinopoisk
Kitsu
kodi
Kodi
Kribs
kubernetescrd
lastplayed
Lavado
lavfi
ldconfig
leresolver
letsencrypt
libc
libera
libmali
libnvcuvid
libnvidia
libplacebo
libva
llvmpipe
localappdata
localtitle
lockdata
lockedfields
logdir
logfile
logfiles
logpath
lshw
LSIO
lzma
machinectl
macvlan
MAINPID
Maxr
maxretry
Mbps
mcarlton
mediaserver
mergerfs
metaarchive
metaimage
metapackage
metapackages
Metapackages
mintls
mirrorbits
mirrorinfo
mirrorlist
mirrorstats
mirrorsync
mkinitcpio
mmdb
mobi
modeset
mopidy
mpaa
mpvqt
Multicore
multiversion
Multiview
musicbox
musicbrainzalbumartistid
musicbrainzalbumid
musicbrainzartistid
musicbrainzreleasegroupid
mycoolname
myjellyfin
myvideos
nasm
Navi
ncmpcpp
newbaseurl
nftables
Niels
nielsvanvelzen
nightlies
Nightmode
noarch
noarchive
noautorunwebapp
nodesource
nodistro
noimageindex
nonfree
noninteractive
Nontranscoded
nosniff
nosnippet
notranslate
nowebclient
nssm
NVDEC
NVENC
nvidiactl
ocid
ocsp
offtopic
OLDFILES
Olivo
OMDB
onevpl
OPTOUT
originaltitle
outros
pacman
Palinuro
partnumber
parttype
𝘱𝘢𝘵𝘩
PGID
PGSSUB
Pictureless
playcount
playerstats
Powerline
privkey
probesize
Profil
PROGRAMDATA
projectname
providernameid
publickey
PUID
Quadro
QUIC
Rabert
Radarr
radeon
Radeon
radeonsi
radeontop
RADV
ratelimits
rclone
RDNA
readthrough
Realtek
redir
redirections
redirector
redirectscheme
referer
releasedate
remoteip
remux
remuxed
remuxing
repofile
rescan
rffmpeg
rgba
rkmpp
RKMPP
rkrga
rkvdec
rkvenc
Robibero
rockchip
Ronin
rpmfusion
RSSDP
rsyncd
Ryzen
scrobble
scrollbuttons
scroller
Scyfin
seasonnumber
secp
secretfilter
seekbar
SEMA
sendfile
Serilog
setsebool
Shoko
Shokofin
shoutcast
showtitle
Skia
skylake
Skylake
Sonarr
sortname
sorttitle
soughtafter
Spacetech
spaghettified
specifishity
speedbumps
splashscreen
SSDP
storebadge
stripsecrets
subcc
subcomponents
subfolders
subheaders
subpackages
subteam
sudoedit
superfast
Swiftfin
synchronised
syncplay
sysconfig
Sysoev
systempaths
tailnet
Themerr
thornbill
Tigerlake
timedatectl
Tizen
TMDB
tmdbid
tmpfs
tonemapping
triaging
trickplay
Trixie
truenas
TSIG
TVDB
tvdbid
tvheadend
tvrageid
tvshow
TXTT
Ultrachromic
ultrafast
unban
unbanip
Uncorr
unsynchronised
Unsynchronized
upvote
usermod
userns
vaapi
vainfo
valhall
Vasily
vdpu
Velzen
Venson
vepu
veryfast
veryslow
videoid
videotoolbox
vitorsemeano
Vium
Vorbis
VORBIS
weba
webclient
webdir
Weblate
webroot
Webroot
Webstorm
webui
wheter
withcolor
withuserdata
Wizdom
wstunnel
xattr
Xbmc
XMLTV
xorg
Xorg
Xvolume
xvzf
ycbcr
youruser
yourusername
+1 -1
View File
@@ -13,7 +13,7 @@ const redirects: ClientRedirects.Options['redirects'] = [
'/docs/general/server/media/subtitles.html',
'/docs/general/server/media/external-files'
],
to: '/docs/general/server/media/movies#external-subtitles-and-audio-racks'
to: '/docs/general/server/media/movies#external-subtitles-and-audio-tracks'
},
// Storage docs moved from the server guide to administrative docs
{
+1 -1
View File
@@ -9,7 +9,7 @@ type PillParams = {
const Pill: FunctionComponent<PillParams> = ({ children, active, onClick }: PillParams) => (
<li
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-to-interactive-role
// eslint-disable-next-line jsx-a11y-x/no-noninteractive-element-to-interactive-role
role='button'
tabIndex={0}
className={clsx('pills__item', { 'pills__item--active': active })}
+4
View File
@@ -13,6 +13,7 @@ import {
SiIos,
SiKodi,
SiLg,
SiSamsung,
SiLinux,
SiRoku,
SiSailfishos,
@@ -98,6 +99,9 @@ const PlatformIcon = ({
case Platform.SailfishOS:
return <SiSailfishos size={size} className={className} />;
case Platform.Tizen:
return <SiSamsung size={size} className={className} />;
case Platform.TVOS:
return <SiAppletv size={size} className={className} />;
-74
View File
@@ -1,74 +0,0 @@
import React from 'react';
import './ContactCard.scss';
const IrcCard = () => (
<div className='card card--contact'>
<div className='card__header'>
<h3>IRC</h3>
</div>
<div className='card__body'>
The official Matrix rooms are also bridged from Matrix to <a href='https://libera.chat'>Libera.chat</a> for
convenience.
<div className='alert alert--secondary margin-top--md'>
<strong>NOTE:</strong> Matrix is the preferred chat platform. IRC is generally not recommended due to a lack of
features and moderation controls.
</div>
<div className='container margin-top--md'>
<div className='row'>
<div className='col col--3 col--offset-3'>
<h4>General Channels</h4>
<ul>
<li>
<a href='ircs://irc.libera.chat:6697/#jellyfin'>#jellyfin</a>
</li>
<li>
<a href='ircs://irc.libera.chat:6697/#jellyfin-announce'>#jellyfin-announce</a>
</li>
<li>
<a href='ircs://irc.libera.chat:6697/#jellyfin-troubleshooting'>#jellyfin-troubleshooting</a>
</li>
<li>
<a href='ircs://irc.libera.chat:6697/#jellyfin-offtopic'>#jellyfin-offtopic</a>
</li>
<li>
<a href='ircs://irc.libera.chat:6697/#jellyfin-translate'>#jellyfin-translate</a>
</li>
</ul>
</div>
<div className='col col--3'>
<h4>Development Channels</h4>
<ul>
<li>
<a href='ircs://irc.libera.chat:6697/#jellyfin-documentation'>#jellyfin-documentation</a>
</li>
<li>
<a href='ircs://irc.libera.chat:6697/#jellyfin-dev'>#jellyfin-dev</a>
</li>
<li>
<a href='ircs://irc.libera.chat:6697/#jellyfin-dev-client'>#jellyfin-dev-client</a>
</li>
<li>
<a href='ircs://irc.libera.chat:6697/#jellyfin-dev-android'>#jellyfin-dev-android</a>
</li>
<li>
<a href='ircs://irc.libera.chat:6697/#jellyfin-dev-ios'>#jellyfin-dev-ios</a>
</li>
<li>
<a href='ircs://irc.libera.chat:6697/#jellyfin-vue'>#jellyfin-vue</a>
</li>
<li>
<a href='ircs://irc.libera.chat:6697/#jellyfin-dev-roku'>#jellyfin-dev-roku</a>
</li>
<li>
<a href='ircs://irc.libera.chat:6697/#jellyfin-dev-python'>#jellyfin-dev-python</a>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
);
export default IrcCard;
@@ -84,7 +84,7 @@ export default function ContributorGuide() {
{contributorOption === ContributorOption.Code && (
<>
<div className='margin-top--md'>
There are a couple ways to get involved with Jellyfin depending on your skillset.
There are a couple ways to get involved with Jellyfin depending on your skill set.
</div>
<div>
<button
@@ -467,7 +467,7 @@ export default function ContributorGuide() {
{otherOption === OtherOption.Troubleshoot && (
<div className='margin-top--md'>
We have a large and diverse userbase, with so many features that the combinations and configurations are
We have a large and diverse user base, with so many features that the combinations and configurations are
almost endless. But as a volunteer-run project, the contributors can often be limited in the help they can
provide. If you are well-versed in Jellyfin&apos;s operation, we welcome you to try to help troubleshoot
problems your fellow users are having. Troubleshooting generally occurs in our{' '}
@@ -4,14 +4,8 @@
padding: 24pt 0;
}
.landing-section:first-child {
border-top: 1px solid #eee;
}
.landing-section:nth-child(even) {
background-color: #172138;
border-top: 1px solid #eee;
border-bottom: 1px solid #eee;
}
.landing-section:last-child {
+6 -2
View File
@@ -6,8 +6,12 @@
*/
html {
-moz-font-feature-settings: 'liga' on;
font-feature-settings: 'liga';
/* Note: "normal" activates all common ligatures */
font-variant-ligatures: normal;
}
code {
font-variant-ligatures: none;
}
:root {
+24
View File
@@ -337,6 +337,30 @@ const officialClients: Array<Client> = [
],
recommended: true
},
{
id: 'jellyfin-Tizen',
name: 'Jellyfin for Tizen',
description: 'The official Jellyfin app for Samsung Tizen devices.',
clientType: ClientType.Official,
deviceTypes: [DeviceType.TV],
licenseType: LicenseType.OpenSource,
platforms: [Platform.Tizen],
primaryLinks: [
{
id: 'samsung-store',
name: 'Smart TV App Store',
url: 'https://www.samsung.com/us/tvs/smart-tv/samsung-tv-apps-detail/?appId=3202007021208'
}
],
secondaryLinks: [
{
id: 'github',
name: 'GitHub',
url: 'https://github.com/jellyfin/jellyfin-tizen'
}
],
recommended: true
},
{
id: 'mopidy',
name: 'Mopidy-Jellyfin',
+22 -1
View File
@@ -29,7 +29,8 @@ export enum Projects {
Vue = 'Jellyfin Vue',
JellyfinWeb = 'Jellyfin Web',
IOS = 'Jellyfin for iOS',
Kodi = 'Jellyfin for Kodi'
Kodi = 'Jellyfin for Kodi',
Documentation = 'Jellyfin Documentation'
}
export enum ProjectRole {
@@ -78,6 +79,16 @@ export const donations: Array<DonationTarget> = [
}
]
},
{
title: 'Jimi (jimdogx)',
roles: [GetProjectRole(Projects.Roku, ProjectRole.Contributor)],
links: [
{
url: 'https://buymeacoffee.com/jimdogx',
name: SponsorTypes.BuyMeACoffee
}
]
},
{
title: 'Niels van Velzen',
roles: [
@@ -193,5 +204,15 @@ export const donations: Array<DonationTarget> = [
name: SponsorTypes.BuyMeACoffee
}
]
},
{
title: 'BotBlake',
roles: [MiscRoles.CommunityMod, GetProjectRole(Projects.Documentation, ProjectRole.Contributor)],
links: [
{
url: 'https://github.com/sponsors/botblake',
name: SponsorTypes.GithubSponsor
}
]
}
];
+2
View File
@@ -13,6 +13,7 @@ enum Platform {
TVOS = 'tvOS',
WebOS = 'webOS',
Xbox = 'Xbox',
Tizen = "Tizen",
// Server platforms
Arch = 'Arch Linux',
@@ -43,6 +44,7 @@ export const FeaturedClientPlatforms = [
Platform.Kodi,
Platform.Roku,
Platform.TVOS,
Platform.Tizen,
Platform.WebOS,
Platform.Xbox
];
+16
View File
@@ -121,5 +121,21 @@ export const ThirdPartyRepositories: Array<PluginRepository> = [
includes: {
'WizdomSubs Downloader': 'https://github.com/DeDuplicate/Jellyfin_wizdomsubs_downloader'
}
},
{
id: 'gh:GeiserX/smart-covers',
name: "GeiserX's SmartCovers Repo",
url: 'https://geiserx.github.io/smart-covers/manifest.json',
includes: {
SmartCovers: 'https://github.com/GeiserX/smart-covers'
}
},
{
id: 'gh:GeiserX/whisper-subs',
name: "GeiserX's WhisperSubs Repo",
url: 'https://geiserx.github.io/whisper-subs/manifest.json',
includes: {
WhisperSubs: 'https://github.com/GeiserX/whisper-subs'
}
}
];
+1 -23
View File
@@ -1,16 +1,13 @@
import Layout from '@theme/Layout';
import React, { useState } from 'react';
import React from 'react';
import DiscordCard from '../components/contact/DiscordCard';
import IrcCard from '../components/contact/IrcCard';
import MatrixCard from '../components/contact/MatrixCard';
import ForumCard from '../components/contact/ForumCard';
import TwitterCard from '../components/contact/TwitterCard';
import MastodonCard from '../components/contact/MastodonCard';
export default function Contact() {
const [isOtherChatVisible, setOtherChatVisible] = useState(false);
return (
<Layout title='Contact'>
<h1 className='text--center margin-top--lg'>Contact</h1>
@@ -30,25 +27,6 @@ export default function Contact() {
<DiscordCard />
</div>
</div>
<div className='row'>
<div className='col margin-bottom--md text--center'>
<button
className='button button--sm button--secondary button--outline'
onClick={() => {
setOtherChatVisible(!isOtherChatVisible);
}}
>
Other
</button>
</div>
</div>
{isOtherChatVisible && (
<div className='row'>
<div className='col col--12 margin-bottom--md'>
<IrcCard />
</div>
</div>
)}
<div className='row'>
<div className='col'>
<h2>Social</h2>
+7 -8
View File
@@ -4,11 +4,11 @@ import { mdiFilter } from '@mdi/js';
import Icon from '@mdi/react';
import Layout from '@theme/Layout';
import clsx from 'clsx';
import React, { useEffect, useState } from 'react';
import React, { useMemo, useState } from 'react';
import ClientDetails from '../../../components/clients/ClientDetails';
import Pill from '../../../components/common/Pill';
import { Client, Clients, DeviceType } from '../../../data/clients';
import { Clients, DeviceType } from '../../../data/clients';
import Platform, { FeaturedClientPlatforms } from '../../../data/platform';
import styles from '../index.module.scss';
@@ -37,7 +37,6 @@ export default function ClientsPage({ recommended = true }: { recommended?: bool
const location = useLocation();
const searchParams = new URLSearchParams(location.search);
const [filteredClients, setFilteredClients] = useState<Client[]>([...Clients]);
const [filter, setFilterValue] = useState<ClientFilter>({
recommended,
deviceTypes: (searchParams.get('type')?.split(',') ?? []) as DeviceType[],
@@ -62,8 +61,8 @@ export default function ClientsPage({ recommended = true }: { recommended?: bool
setFilterValue(filter);
};
useEffect(() => {
setFilteredClients(
const filteredClients = useMemo(
() =>
Clients.filter((client) => {
let result = true;
@@ -81,9 +80,9 @@ export default function ClientsPage({ recommended = true }: { recommended?: bool
(filter.platforms.length === 0 || client.platforms.some((platform) => filter.platforms.includes(platform)));
return result;
})
);
}, [filter, setFilteredClients]);
}),
[filter]
);
return (
<Layout title='Clients'>
+8 -8
View File
@@ -13,13 +13,14 @@ import { UAParser } from 'ua-parser-js';
import styles from './index.module.scss';
import ExternalLinkIcon from '@theme/Icon/ExternalLink';
export default function DownloadsPage({ osType }: { osType?: OsType }) {
export default function DownloadsPage(options: { osType?: OsType }) {
const [isStableLinks, setIsStableLinks] = useState<boolean>(true);
const [isStableHelpVisible, setIsStableHelpVisible] = useState<boolean>(false);
const [activeButton, setActiveButton] = useState<string>();
const isBrowser = useIsBrowser();
let osType = options.osType;
if (isBrowser && osType === undefined) {
const parser = new UAParser(navigator.userAgent);
const os = parser.getOS();
@@ -139,13 +140,12 @@ export default function DownloadsPage({ osType }: { osType?: OsType }) {
{isStableHelpVisible && (
<Admonition type='tip' title='Stable or Unstable?'>
<p>
Generally, if you&apos;re a new user or don&apos;t want your server to change often, use the Stable version.
If you want to help test the latest improvements and features and can handle some occasional breakage,
use the Unstable version. New Unstable releases are published Weekly on Monday mornings (~05:00 UTC).
NOTE: Always back up your existing configuration before testing Unstable releases as there is NO
DOWNGRADE PATH; you must restore your Stable configuration from a backup.
For more details, [please see this documentation](/docs/general/testing/upgrading-and-downgrading).
Generally, if you&apos;re a new user or don&apos;t want your server to change often, use the Stable
version. If you want to help test the latest improvements and features and can handle some occasional
breakage, use the Unstable version. New Unstable releases are published Weekly on Monday mornings
(~05:00 UTC). NOTE: Always back up your existing configuration before testing Unstable releases as there
is NO DOWNGRADE PATH; you must restore your Stable configuration from a backup. For more details,
[please see this documentation](/docs/general/testing/upgrading-and-downgrading).
</p>
</Admonition>
)}
+3 -1
View File
@@ -28,7 +28,9 @@ export default function Home() {
Download Now
</Link>
</div>
<p><a href="/docs/general/community-standards/servers">Note: We do not run servers for users.</a></p>
<p>
<a href='/docs/general/community-standards/servers'>Note: We do not run servers for users.</a>
</p>
</Hero>
<main>
<HomepageFeatures />
Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 195 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 172 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 421 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 585 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 177 KiB

Some files were not shown because too many files have changed in this diff Show More