Sign inSign up

martin0313/multimedia-viewer

By martin0313

•Updated 6 days ago

OpenList 的按需多媒体预览服务:RAW / HEIC / 冷门视频实时转码,不落盘不缓存

Image
0

78

martin0313/multimedia-viewer repository overview

⁠multimedia-viewer

给 OpenList 用的按需多媒体预览服务:把浏览器放不出来的 RAW 照片、HEIC 图片和冷门视频容器,实时转成能直接看的格式。

不落盘、不缓存、不预生成缩略图 —— 点一次算一次,算完立刻删。

⁠特性

  • RAW(CR2 / CR3 / NEF / ARW / DNG / RAF / ORF / RW2 / PEF / SRW / …):优先用 exiftool 抽取文件内嵌的 JPEG 预览(几十毫秒),抽不到再退回 vips 全解码
  • HEIC / HEIF / HIF:libvips(libheif)优先,失败自动回退 heif-convert
  • 普通图片(JPG / PNG / WebP / TIFF / BMP / AVIF / GIF):vips 生成缩略图,限制最大边长,小图不放大
  • 视频(MP4 / MOV / MKV / AVI / WMV / TS / M2TS / FLV / …):ffmpeg 实时转 H.264 + AAC 的 fragmented MP4,边转边推给浏览器
  • 无状态:每个请求建一个临时目录,finally 里删干净;容器重启不丢任何东西
  • SSRF 防护:只允许代理 ALLOW_HOSTS 里的主机

⁠快速开始

docker run -d --name multimedia-viewer \
  --restart unless-stopped \
  -p 8080:8080 \
  -e OPENLIST_BASE=http://192.168.31.100:5244 \
  -e ALLOW_HOSTS=192.168.31.100,127.0.0.1,localhost \
  martin0313/multimedia-viewer:latest

docker compose:

services:
  multimedia-viewer:
    image: martin0313/multimedia-viewer:latest
    container_name: multimedia-viewer
    restart: unless-stopped
    ports:
      - "8080:8080"
    environment:
      TZ: Asia/Shanghai

⁠环境变量

变量默认值说明
PORT8080监听端口
MAX_BYTES419430400(400 MB)单个源文件体积上限,超过直接拒绝
MAX_W1600输出图片最大边长(等比缩,不放大)
OPENLIST_BASEhttp://192.168.31.100:5244OpenList 站点地址,用于把相对路径补全
ALLOW_HOSTS192.168.31.100,127.0.0.1,localhost允许代理的主机白名单,逗号分隔
OPENLIST_TOKEN空可选。OpenList 后台「设置 → 其他」里的 Token,只发给白名单主机

⁠端点

路径说明
/healthz健康检查,返回 ok
/viewer?url=<文件地址>预览页:图片出 <img>,视频出 <video>
/viewer?url=<文件地址>&bare=1同上,但去掉顶栏(文件名/大小/下载链接)与留白,纯媒体铺满
/p?url=<文件地址>转成 JPEG 返回(image/jpeg)
/v?url=<文件地址>转码后以 chunked 流式返回(video/mp4)
/meta?url=<文件地址>返回 {"size": 字节数},取不到则为 null

url 可以是完整 URL,也可以是相对 OpenList 根目录的路径(会拼 OPENLIST_BASE)。带 ?sign=xx&expire=yy 的签名直链原样粘贴即可,不会被 & 截断。

⁠bare 模式

加 &bare=1(也可以写 true / yes / on)后,页面只剩媒体本身:

  • 删掉顶栏(文件名、大小、下载链接),也不再请求 /meta
  • 背景纯黑、overflow:hidden、无 padding/圆角/阴影
  • 图片 max-width/height:100% 等比缩放不裁切不放大;视频 object-fit:contain 铺满并保留播放控件

这个模式是给 OpenList 的 iframe 预览弹窗用的 —— 弹窗本身已经有文件名和下载按钮,再套一层顶栏会重复,且 100vh 在 iframe 里容易出滚动条。直接浏览器打开(不带 bare)仍是带信息的完整页面。

注意 &bare=1 必须放在 $e_url 后面,前端只做变量替换,不认其它语义。

⁠接到 OpenList 的 iframe 预览

后台 → 设置 → 预览 → iframe 预览,加一组(只放 OpenList 自己放不出来的格式):

"arw,cr2,cr3,nef,dng,raf,orf,rw2,pef,heic,heif,mkv,avi,wmv,ts,m2ts,flv": {
  "Multimedia Viewer": "http://192.168.31.100:8080/viewer?url=$e_url&bare=1"
}

$e_url 是 OpenList 文档定义的 encodeURIComponent(文件URL),正好对上 /viewer?url=。

如果你那边 sign_all 打开导致 $url 不带签名而返回 401,就把 OPENLIST_TOKEN 配上,或在「外部预览」里用「复制直链」粘贴使用。

⁠已知限制

  • 视频每次播放都会重新转码,CPU 开销实打实;并发播放会互相抢 CPU
  • 视频是 chunked 流,没有 Range 支持,不能拖动进度条
  • 源文件先完整下载到临时目录再处理,不吃磁盘但吃时间;超过 MAX_BYTES 直接拒绝
  • 没有缩略图缓存:同样的文件看两次,算两次

⁠镜像内容

python:3.12-slim + 以下工具(Debian 13):

工具版本
libvips8.16.1
exiftool13.25
ffmpeg7.1.5
libheif / heif-convert1.23.6

镜像约 724 MB(未压缩)。

⁠License

MIT

Tag summary

Content type

Image

Digest

sha256:c91301383…

Size

250.6 MB

Last updated

6 days ago

docker pull martin0313/multimedia-viewer