This commit is contained in:
juneix
2026-03-07 13:01:39 +08:00
parent f0b921d603
commit 0ae9155c2f
22 changed files with 5731 additions and 1608 deletions
Vendored
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+47
View File
@@ -0,0 +1,47 @@
name: Build and Push Docker Image
on:
push:
branches:
- main
paths-ignore:
- 'README.md'
- 'README_zh.md'
- '.github/**'
workflow_dispatch:
# 使用 concurrency 结合延迟效果来实现类似“修改后30分钟构建”的需求是不太直接的。
# 通常 GitHub Actions 在 push 后立即触发。
# 如果需要“合并触发”,可以使用 workflow_run 或在 push 触发时先 sleep。
# 但为了可靠性,这里采用标准的 push 触发,并配合并发限制。
jobs:
docker:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up QEMU
uses: actions/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: actions/setup-buildx-action@v3
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: |
ghcr.io/${{ github.repository_owner }}/embyx:latest
cache-from: type=gha
cache-to: type=gha,mode=max
+26
View File
@@ -0,0 +1,26 @@
# Dockerfile for EmbyX
FROM nginx:alpine
# 设置工作目录存放原始语言包
WORKDIR /app
# 复制中英文版本到镜像内部存放
COPY zh/ /app/dist/zh/
COPY en/ /app/dist/en/
# 复制 nginx 配置
COPY nginx.conf /etc/nginx/conf.d/default.conf
# 复制并设置启动脚本
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
# 预设默认语言和端口环境变量
ENV APP_LANG=en
ENV APP_PORT=8090
# EXPOSE 在 host 模式下仅作声明
EXPOSE 8090
# 使用自定义脚本启动
ENTRYPOINT ["/entrypoint.sh"]
+99 -2
View File
@@ -1,2 +1,99 @@
# EmbyX
像刷抖音一样看 Emby 短视频。Watch Emby short videos like Tiktok.
# 📱 EmbyX Vertical Player `v1.1`
[中文说明](./README_zh.md) | [English Documentation](./README.md)
> A TikTok-style web interface for Emby / Jellyfin, designed for browsing and managing short videos in an immersive way.
---
## ✨ Features
- **Fluid Playback**: TikTok-style vertical scrolling, immersive full-screen experience.
- **Grid View**: Browse with cover walls, supports pagination and random refresh.
- **Direct Play**: Works natively on modern devices. Support for 8K, AV1, and HEVC without transcoding.
- **Library Sync**: One-tap to favorite/unfavorite videos, fully synced with Emby server.
- **Key & Mouse Support**: Complete keyboard shortcut mapping. Friendly for TV and PC browsers.
- **PWA Ready**: Install as a desktop or home screen app.
- **Privacy First**: All data is stored locally; nothing is uploaded to the cloud.
---
## 🔮 Playback Performance
| Device | HEVC Decode | AV1 Decode |
|:---:|:---:|:---:|
| Apple | A9 (2015) / M1 | A17 Pro (2023) / M3 |
| Android | Budget (2016) | Budget (2024) |
| PC | Intel Core 6-8th Gen (iGPU) | Intel Core 11th Gen+ (iGPU) |
---
## ⌨️ Shortcuts Guide
| Key | Function |
|:---:|---|
| `W / S / ↑ / ↓` | Previous / Next Video |
| `A / D / ← / →` | Seek Back / Forward 15s |
| `Space / Click OK` | Pause / Play |
| `U / Double Click OK` | Favorite Video |
| `J / Menu Key` | Toggle Aspect Ratio |
| `M` | Toggle Mute |
| `I` | Open Settings / Profile |
| `E` | Toggle View Mode (List/Grid) |
| `R` | Sequential / Random Mode |
| `F` | Fullscreen Mode |
| `G` | Toggle Libraries |
| `V` | Show File Info |
---
## 📁 Directory Structure
```
embyx/
├── zh/ # Chinese Version
│ ├── index.html
│ ├── manifest.json
│ └── ...
├── en/ # English Version
│ ├── index.html
│ ├── manifest.json
│ └── ...
├── README.md # English (Default)
└── README_zh.md # Chinese
```
---
## 🚀 Deployment
### Option 1: Direct File Hosting (Recommended)
Simply put all files from either `zh/` or `en/` folder into your web server (Nginx, Apache, etc.).
### Option 2: Docker Deployment
One image, multiple languages. Controlled by environment variable.
```bash
docker run -d \
--name embyx \
--network host \
-e APP_LANG=en \
-e APP_PORT=8090 \
ghcr.io/juneix/embyx:latest
```
| Env | Description | Default |
|---|---|---|
| `APP_LANG` | `en` (English) / `zh` (Chinese) | `en` |
| `APP_PORT` | The port the container will listen on | `8090` |
---
## 📝 License
MIT License — Feel free to use, PRs and Issues are welcome.
👨🏻‍💻 Author: [@Juneix](https://juneix.github.io)
🛜 Official Site: [June's Hub](https://5nav.eu.org)
+150
View File
@@ -0,0 +1,150 @@
# 📱 EmbyX 竖屏播放器 `v1.1`
> 这是一个技术小白借助 Antigravity 和 Emby API 制作的 Web 应用,仿抖音风格浏览、管理 Emby 的短视频。
---
## ✨ 功能特色
- **流式播放**:抖音风格上下滑动,沉浸式全屏体验
- **格子视图**:封面墙浏览,支持分页与随机换一批
- **直接播放**Direct Play):安卓 AV1、8K 不转码
- **收藏管理**:一键收藏 / 取消,同步 Emby 数据库
- **键鼠适配**:完整键盘快捷键,电视/电脑浏览器友好
- **PWA 支持**:可安装为桌面/主屏幕应用
- **私有化部署**:数据本地存储,不上传云端
---
## 🔮 播放性能
| 设备 | HEVC 硬解 | AV1 硬解 |
|:---:|:---:|:---:|
| 苹果 | A9 (2015) / M1 | A17 Pro (2023) / M3 |
| 安卓 | 千元机 (2016) | 千元机 (2024) |
| PC | 6~8 代酷睿·核显 | 11 代酷睿·核显 |
---
## ⌨️ 快捷键指南
| 按键 | 功能 |
|:---:|---|
| `W / S / ↑ / ↓` | 上一个 / 下一个视频 |
| `A / D / ← / →` | 快退 / 快进 15 秒 |
| `Space / 单击 OK` | 暂停 / 播放 |
| `U / 双击 OK` | 收藏视频 |
| `J / 菜单键` | 比例切换 |
| `M` | 音量开关 |
| `I` | 个人中心 |
| `E` | 视图切换 |
| `R` | 顺序 / 随机 |
| `F` | 全屏切换 |
| `G` | 选择媒体源 |
| `V` | 流媒体详情 |
---
## 🧩 使用技巧
- **原生全屏**:iOS 系统限制,不支持全屏按钮
- **PWA 应用**:浏览器 📲 添加到主屏幕 / 作为应用安装
- **键鼠适配**:电脑、电视浏览器也能快乐摸鱼
- **媒体库建议**:单个媒体库建议不超过 **1000 个视频**,可建立多个媒体库分层管理
---
## 🛠️ 技术栈
| 层级 | 技术 |
|---|---|
| **结构** | HTML5 语义化标签 |
| **样式** | Tailwind CSSCDNJIT 按需) |
| **逻辑** | 原生 JavaScript(无框架) |
| **图标** | Lucide IconsCDN |
| **数据** | Emby REST API |
| **离线支持** | Service WorkerPWA |
| **容器** | Nginx AlpineDocker 部署时) |
---
## 📁 文件目录
```
embyx/
├── index.html # 核心文件,包含所有逻辑与样式
├── poster.webp # 自定义默认封面图(可替换)
├── manifest.json # PWA 配置文件
├── sw.js # Service Worker(离线缓存)
├── icon.png # PWA 图标
├── Dockerfile # Docker 镜像构建文件
└── docker-compose.yml # 一键部署配置
```
---
## 🚀 部署方式
### 方式一:直接部署(推荐个人用户)
将以下文件放入任意 Web 服务器(Nginx、Apache、NAS 静态服务等)根目录:
```
index.html
poster.webp
manifest.json
sw.js
icon.png
```
> **尝鲜玩法**:手机可以直接双击 `index.html`file:// 协议)本地使用,通过 HTTP 访问 Emby。
---
### 方式二:Docker 部署
#### 使用 Docker
```bash
# 拉取最新镜像
docker pull ghcr.io/juneix/embyx:latest
# 运行容器(映射到本机 8080 端口)
docker run -d \
--name embyx \
--network host \
-e APP_LANG=zh \
-e APP_PORT=8090 \
--restart unless-stopped \
ghcr.io/juneix/embyx:latest
```
访问 `http://your-server-ip:8080` 即可使用。
#### 使用 docker-compose(推荐)
```bash
# 下载 docker-compose.yml 后执行
docker compose up -d
```
或者直接复制到群晖、飞牛、Dockge 的 docker-compose 模板:
```bash
services:
embyx:
image: ghcr.io/juneix/embyx:latest
container_name: embyx
restart: unless-stopped
network_mode: host
environment:
- APP_LANG=zh # zh (中文), en (英文)
- APP_PORT=8090 # 在 host 模式下,直接定义访问端口
```
---
## 📝 开源协议
MIT License — 随意使用,欢迎 PR 和 Issue。
👨🏻‍💻 作者:[@谢週五](https://juneix.github.io)
🛜 官网:[谢週五の藏经阁](https://5nav.eu.org)
+9
View File
@@ -0,0 +1,9 @@
services:
embyx:
image: ghcr.io/juneix/embyx:latest
container_name: embyx
restart: unless-stopped
network_mode: host
environment:
- APP_LANG=zh # zh (中文), en (English)
- APP_PORT=8090 # 访问端口 (Access Port)
View File

Before

Width:  |  Height:  |  Size: 132 KiB

After

Width:  |  Height:  |  Size: 132 KiB

+2535
View File
File diff suppressed because it is too large Load Diff
View File
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

+17
View File
@@ -0,0 +1,17 @@
const CACHE_NAME = 'embyx-v1';
// 安装阶段:不强制缓存大量资源,保持轻量
self.addEventListener('install', (event) => {
self.skipWaiting();
});
// 激活阶段:清理旧缓存
self.addEventListener('activate', (event) => {
event.waitUntil(clients.claim());
});
// 核心:必须有 fetch 处理器才能触发安卓 Chrome 的安装横幅
self.addEventListener('fetch', (event) => {
// 默认直接透传,不做离线缓存以节省空间和避免版本更新延迟
event.respondWith(fetch(event.request));
});
+28
View File
@@ -0,0 +1,28 @@
#!/bin/sh
set -e
# 默认参数
APP_LANG=${APP_LANG:-en}
APP_PORT=${APP_PORT:-8090}
echo "Current Configuration:"
echo " - Language: $APP_LANG"
echo " - Port: $APP_PORT"
# 动态修改 Nginx 监听端口
sed -i "s/listen 80;/listen ${APP_PORT};/g" /etc/nginx/conf.d/default.conf
# 清理 web 根目录
rm -rf /usr/share/nginx/html/*
# 根据环境变量选择性“部署”
if [ "$APP_LANG" = "zh" ]; then
echo "Deploying Chinese version..."
cp -rf /app/dist/zh/* /usr/share/nginx/html/
else
echo "Deploying English version..."
cp -rf /app/dist/en/* /usr/share/nginx/html/
fi
# 启动 nginx
exec nginx -g "daemon off;"
+12 -1605
View File
File diff suppressed because it is too large Load Diff
+33
View File
@@ -0,0 +1,33 @@
server {
listen 80;
server_name _;
root /usr/share/nginx/html;
index index.html;
# MIME types
types {
text/html html htm;
application/json json;
application/manifest+json webmanifest;
text/javascript js;
image/webp webp;
image/png png;
}
# Service Worker: No caching
location = /sw.js {
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
}
# Static assets: Long-term cache
location ~* \.(png|webp|ico)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}
# SPA/PWA routing support
location / {
try_files $uri $uri/ /index.html;
}
}
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

+2736
View File
File diff suppressed because it is too large Load Diff
+21
View File
@@ -0,0 +1,21 @@
{
"name": "EmbyX",
"short_name": "EmbyX",
"start_url": "./index.html",
"display": "standalone",
"background_color": "#000000",
"theme_color": "#000000",
"description": "Emby Short Video Player",
"icons": [
{
"src": "icon.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "icon.png",
"sizes": "512x512",
"type": "image/png"
}
]
}
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

+17
View File
@@ -0,0 +1,17 @@
const CACHE_NAME = 'embyx-v1';
// 安装阶段:不强制缓存大量资源,保持轻量
self.addEventListener('install', (event) => {
self.skipWaiting();
});
// 激活阶段:清理旧缓存
self.addEventListener('activate', (event) => {
event.waitUntil(clients.claim());
});
// 核心:必须有 fetch 处理器才能触发安卓 Chrome 的安装横幅
self.addEventListener('fetch', (event) => {
// 默认直接透传,不做离线缓存以节省空间和避免版本更新延迟
event.respondWith(fetch(event.request));
});
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB