本文主要讨论自托管媒体库(以 Octans 一类 Linux 后端为例)如何接入远程片库:WebDAV、SMB、NFS 各自适合什么场景,时延与鉴权差在哪里,锁与一致性能指望多少,以及在 Docker / 容器部署里「系统挂载」和「进程内直接连协议」该怎么选。

默认媒体库往往只认本地路径:有绝对路径、FileStream 可 seek、FFmpeg / MediaInfo 直接吃 path,缓存与权限交给操作系统。片库一旦落在 NAS、网盘或另一台 Linux 导出目录上,就需要明确两条路线:

路线做法后端看到的是什么
挂载再扫mount.cifs / mount.nfs / WebDAV FUSE / rclone mount 等本地目录,继续走 path 模型
直接 Provider后端进程用协议枚举、stat、按 offset 读URI / handle,无稳定本地 path

两条都能「看得到文件」,但运维边界、故障面和播放 Range 代理的实现成本完全不同。下面按协议拆开,再收口到推荐顺序。

为什么「本地 path」不够用

远程接入后,下列假设会逐一失效:

  • 文件不一定有可给 FFmpeg 直接打开的本地路径。
  • 目录枚举变成 PROPFIND、SMB query directory、NFS READDIR(PLUS)
  • 随机读变成 HTTP Range、SMB READ(offset)、NFS READ(offset)
  • 变更标识不统一:ETag、mtime、inode / fileid、change attribute 能力各异。
  • 断线、鉴权过期、权限变化都要由接入层处理,而不是只靠内核 client。

因此更稳的模型是:媒体库 = Storage Provider + Root,条目存 ProviderUri + RelativePath,凭据走独立的 CredentialRef,密码绝不写进 URI。

对播放侧,前端应始终看到统一 HTTP 接口,例如:

GET /api/media/{id}/stream
Range: bytes=1048576-2097151

后端解析 Range,再调用对应 provider 的 range read,返回 206 Partial Content。不要假设远程 stream 可以先整文件打开再交给框架自动 Range——远程场景应只拉客户端请求的那段字节。

分析链路(ffprobe / MediaInfo / 截图)更适合 Materialize:按需把块或临时文件落到本地缓存,再交给工具链;把「FFmpeg 直接读 smb:// / webdav:// / nfs://」当主路径依赖编译选项与发行构建,不稳定,也不应作为产品硬约束。

总表:三协议怎么比

维度WebDAVSMBNFS
网络底座HTTP/HTTPSTCP 445(SMB2/3)RPC / NFS,版本相关
目录枚举PROPFINDquery directoryREADDIR / READDIRPLUS
随机读HTTP Rangeoffset READoffset READ
时延特征每请求 HTTP 往返;易被反代/TLS 放大会话可复用,大文件读可做得很稳内网常最快,取决于 rsize 与缓存
鉴权Basic / Digest / Bearer / App Password 等用户密码 / domain;企业侧 AD / KerberosAUTH_SYS(uid/gid)或 Kerberos
锁 / 一致性协议有锁,媒体只读库几乎用不上有共享/排他打开语义;扫库轮询更稳v3 偏弱一致;v4 状态更重
容器挂载较少默认装 FUSE WebDAVmount.cifs 常见但权限与凭据要设计mount.nfs 成熟,端口/防火墙要注意
直接接入成熟度中低
工程复杂度低到中中到高
闭源商用库风险低(HTTP + MIT client)中到高(LGPL / 商业授权)中到高(LGPL / 商业 SDK)
建议阶段Phase 1Phase 2Phase 3

只读媒体库第一阶段建议统一:不写、不删、不改远端。写能力会引入冲突、锁、误删与审计,应后置。

WebDAV:最适合先打通的远程库

定位

WebDAV 是 HTTP 扩展(资源属性、collection、命名空间等)。对媒体库而言,关键是:

  • 列表:PROPFIND(工程上用 Depth: 1,自己控递归,避免 Depth: infinity)。
  • 属性:getetag / getlastmodified / getcontentlength
  • 读文件:GET;拖动播放:GET + Range

部署面很广:Nextcloud / ownCloud、群晖 / QNAP 的 WebDAV、坚果云、Apache mod_dav 等。HTTPS、反向代理、Bearer / App Password 与现有 Web 运维习惯一致。

时延

  • 扫描是大量小请求:PROPFIND 深度与并发要限流,否则把 NAS 或网盘 API 打满。
  • 播放时延取决于 TLS、代理缓冲和是否真支持 Range。
  • 远端若忽略 Range 直接回 200,不能把「从中间字节起」的请求原样转给播放器;应走缓存 materialize 或明确失败。

鉴权

常见:Basic(务必 HTTPS 或明确内网豁免)、Digest、Bearer、网盘 App Password、反代注入。凭据加密落库,URI 只保留 root;连接测试可走 OPTIONS + root PROPFIND + 小文件 HEAD/GET

WebDAV 有锁语义,但只读片库扫描与播放几乎不依赖。变更检测用 ETag / mtime / size 轮询即可;不要假设 ETag 一定存在或格式统一。

容器与挂载

  • 直接 Provider:容器只需出网访问 WebDAV URL,不需要 FUSE 特权,和 Compose 私有化部署模型更合拍。
  • 挂载路线:davfs2 / rclone mount 等会引入 FUSE、特权与进程生命周期;适合管理员自管挂载点,不适合当产品默认依赖。

实现上可用 MIT 的 WebDAV client 做元数据,HttpClient 自己控 Range、超时、重试与取消——播放代理需要精确对应前端与远端的字节范围。

SMB:用户价值高,工程与合规都要先拍板

定位

NAS、Windows 共享、Samba / homelab 片库大量走 SMB。Linux 后端若用内核 CIFS mount,就要用户态 SMB2/SMB3 client:协商 dialect → session → tree connect → open → READ(offset)

时延

  • 会话与 tree connect 复用得好时,大文件顺序/随机读可以很稳。
  • 每个 Range 都完整建连会灾难性放大首字节时延。
  • 推荐分层池化:ConnectionSessionTreeConnect → 短期 FileHandle;chunk 常见 1–8MB,按压测调。
  • 断线后应重新 open,从 offset 续读,而不是让播放器整段失败。

鉴权

MVP:server、port(默认 445)、share、可选 domain、username、password。企业侧再谈 Kerberos / AD、signing required、encryption required、DFS。AD 场景还牵扯时间同步、SPN、DNS、workgroup/domain 混用——产品文档要把「家庭 NAS 密码」和「域环境」分成两档能力。

锁与打开语义

SMB 打开模式、共享删除/写冲突比 WebDAV 更「文件共享」。只读库可固定只读打开;第一阶段不要依赖 change notification,扫库用 size + mtime +(若有)file id 轮询更简单可靠。禁用 SMB1,默认只谈 SMB2/SMB3。

容器与挂载

方式要点
宿主机 mount.cifs 后 bind 进容器运维熟悉;凭据、uid/gid、重连、soft/hard 要在宿主机设计;容器仍当本地盘
容器内 mount常需特权 / CAP,安全边界差,一般不推荐产品默认
进程内 SMB provider镜像无需 CIFS 内核模块;但要 native 库或托管库,以及连接池与合规

库路线(闭源商用尤甚):纯 C# 库常带 LGPL-3.0,稳妥可走商业授权;用户态 libsmb2 一类为 LGPL-2.1-or-later,动态链接 + 可替换 + 许可证文本是常见合规设计。默认闭源路径不建议绑 Samba libsmbclient,除非法务与发行模式都审过。对外宣传「SMB 兼容」时,协议/IP 评估应进法务清单,公开规范 ≠ 自动免责。

NFS:内网性能好,直接接入最容易被低估

定位

Linux / Unix NAS 导出目录常见 NFS。内核 NFS client 已经处理了大量缓存、重连与权限细节;一旦改成进程内直接接入,这些复杂度会落到 provider 或第三方库上。

时延

  • 同机房、调好 rsize / 并发时,吞吐与时延往往优于「每块一次 HTTPS」的 WebDAV。
  • 元数据与数据缓存策略错误时,会出现「stat 很快、列表抖动、播放中 stale handle」等难查问题。
  • 直接接入时要自管:元数据 TTL、大目录分页、预读 chunk、错误退避。

鉴权与权限

版本倾向鉴权产品化注意
NFSv3多为 AUTH_SYS(客户端声明 uid/gid)适合可信内网;root_squash / anonuid / anongid 会改写身份
NFSv4.x更现代;企业侧常见 Kerberos(krb5 / krb5i / krb5p)KDC、principal、keytab、时间同步、DNS;不能简化成「填个密码」

uid/gid 配置只应给管理员,且默认只读;权限失败要能区分 permission denied、export denied、stale file handle。

锁与一致性

NFSv3 偏无状态,缓存一致性是弱模型,不是强一致。扫库用 size + mtime + file handle / change attribute;播放中文件被替换时,当前 stream 可读到失败再 re-stat。stale file handle 要重新 lookup,不能假设 handle 永久有效。v4 的锁与 session 更完整,直接实现成本也更高——MVP 可只做 NFSv3 AUTH_SYS + 只读。

容器与挂载

  • mount.nfs(v3):可能涉及 portmapper、mount 协议与多端口,防火墙与安全组要放行;挂成功后容器 bind-mount 只读媒体卷即可,和「媒体只读挂载」的 Compose 习惯一致。
  • NFSv4:端口模型通常更简单,但仍要处理 idmap 与(若启用)Kerberos 侧车或宿主机票据。
  • 直接 Provider:可用 libnfs 等用户态库(注意 library 与 examples 许可证不同,勿把 GPL examples 拷进产品);企业也可评估商业 NFS SDK。无论哪条,都不要默认把「容器里再 mount 一次」写成唯一官方路径。

挂载 vs 直接 Provider:怎么选

考量先挂载再扫本地进程内直接 Provider
开发速度快,现有 path 代码可复用需抽象 List / Stat / ReadAt / Materialize
容器部署依赖宿主机或特权 mount镜像自包含协议客户端,权限面更清晰
多库多凭据每个挂载点一份 fstab/systemd库级 CredentialRef,更易多租户式配置
播放 RangeOS 页缓存 + 本地 seek自研代理,精确按 Range 拉远端
故障可见性挂载 stale、df 卡住,应用层难诊断错误可映射到库级状态与连接测试
适用单机 homelab、管理员自管 NAS 挂载产品化远程库、多协议、要统一运维体验

实践上可以并存:高级用户继续把 SMB/NFS 挂到宿主机再 bind 进容器(见 Docker 私有化部署里的媒体只读卷);产品能力则按 Provider 分阶段交付,不把 FUSE/rclone 当核心依赖。

推荐落地顺序

Phase 0  Provider 抽象 + Range 代理 + Materialize / 元数据缓存 + 连接测试
Phase 1  WebDAV(HttpClient + 轻量 WebDAV client)
Phase 2  SMB(先定库与授权:商业授权 C# 库 或 LGPL 动态链接 native)
Phase 3  NFS(只读 MVP:v3 AUTH_SYS → 再谈 v4 / Kerberos)
Phase 4  扩展:SFTP、S3 兼容、rclone 集成等

验收时至少覆盖:大目录分批扫描、10GB 级视频拖动播放、断线恢复、鉴权失败可诊断、(SMB)无 SMB1、(NFS)root_squash / stale handle 有明确行为。

安全底线:远程库配置仅管理员;WebDAV/HTTP 防 SSRF(默认拦 loopback / link-local / 云 metadata 段,除非显式放开);路径规范化拒绝 ..;限制单次扫描目录/文件数与响应体大小;日志永不打印密码、token、keytab。

实践建议(收口)

  1. 先抽象,再堆协议:没有统一 List / Stat / ReadAt / Materialize,每加一个协议都会重写扫描与播放。
  2. 播放统一走后端 Range 代理;分析链路默认 Materialize,不赌 FFmpeg 协议栈。
  3. 协议优先级:WebDAV → SMB → NFS;NFS 直接接入成本高于「内网挂上很香」的直觉。
  4. 容器部署:能 Provider 直连就不要为默认路径申请 FUSE/特权;宿主机 mount 作为运维可选项写清凭据与重连。
  5. 只读优先;锁与写冲突等第二阶段再产品化。
  6. 闭源商用把 LGPL 动态链接 / 商业授权、SMB 协议评估写进发布检查单,而不是上线后再补。

相关阅读

同系列还可对照:

来源

本文综合改写自 Octans 项目 research 层《Linux 服务端直接接入 WebDAV / SMB / NFS》备忘录。协议行为、库许可证与部署建议已按公开工程实践概括;具体 SDK 版本、NAS 固件差异与闭源合规以目标环境实测及正式法务审查为准,本文不构成法律意见。