实际上这个问题我在去年暑假的时候就注意到了,GitHub的issue里面也有反映过这种情况[1][2]。我通过WebDAV将NAS挂载到Finder上,当我播放里面的电影时,Finder会卡住(有时候哪怕只是单击这个文件也会,存在一定概率,搞不懂为什么),然后webdavfs_agent会下载大量缓存(至少几个G,并且每次大小还都不一样)到本地,IINA才开始播放。这是IINA或MPV的原因,还是Finder或webdavfs_agent的原因?我希望我能把这个问题弄清楚。
【未完待续】
尝试1
直接从Finder双击文件打开IINA,webdavfs_agent会缓存几个G再开始播放;拖动进度条的时候则有概率出现两种情况:一是先缓存好一会再接着播放,二是直接结束播放而不是继续缓存,也是一个奇怪的bug。使用Infuse播放也是同样的情况。
尝试2
IINA也可以打开URL播放其中的视频,当我打开WebDAV的URL(http://user:password@webdav.me/xxx.mkv)时,可以发现IINA立即开始了播放,就跟看在线视频一样一边播放一边缓存。因此可以看出,对于http,IINA是支持流式播放的,且不会一下子下载太多缓存。
尝试3
用Python写一个脚本,读取文件的前10个字节,Python立即输出了结果,不需要等待大量缓存。因此,webdavfs_agent同样支持只传输少量数据。
filename = "/Volumes/webdav.me/xxx.mkv" with open(filename, 'rb') as f: c = f.read(10) print(c)
IINA或MPV是否能判断文件是否来自WebDAV?
通过fstatfs()调用[3],可以得到一个文件的文件系统类型,于是我写了个程序来输出文件的文件系统类型,运行输出的结果是“webdav”,说明系统是可以得知该文件是否为本地文件的。
#include#include #include #include #include int main() { struct statfs fs; int fd = open("/Volumes/webdav.me/xxx.mkv", O_RDONLY); fstatfs(fd, &fs); printf("%s\n", fs.f_fstypename); close(fd); return 0; }
在MPV的源码中,也可以看到这一部分的判断[4]:
#if HAVE_BSD_FSTATFS static bool check_stream_network(int fd) { struct statfs fs; const char *stypes[] = { "afpfs", "nfs", "smbfs", "webdav", "osxfusefs", "fuse", "fusefs.sshfs", "macfuse", NULL }; if (fstatfs(fd, &fs) == 0) for (int i=0; stypes[i]; i++) if (strcmp(stypes[i], fs.f_fstypename) == 0) return true; return false; }
是Finder的问题吗?
IINA支持在浏览器中通过URL scheme调用(iina://open?url=/Volumes/webdav.me/xxx.mkv)。然而,通过这种方式打开,效果是一样的。看样子还得webdavfs_agent背锅。
编译webdavfs
从[5]下载源码,用Xcode打开。
【待续】
怎么解决?
目前来看,最直接的办法就是通过URL来打开,但是这样操作起来还是比较麻烦。其他第三方的WebDAV挂载工具不知道能不能解决这个问题,没试过。如果要自己开发一个的话,我的想法是利用苹果的File Provider来实现,双击文件的时候可以直接调用IINA的URL scheme并通过http来打开,不知道是否可行,有空可以试试。
参考
[1] https://github.com/iina/iina/issues/3449
[2] https://github.com/iina/iina/issues/1266
[3] https://man.freebsd.org/cgi/man.cgi?query=fstatfs
[4] https://github.com/mpv-player/mpv/blob/master/stream/stream_file.c
[5] https://github.com/apple-oss-distributions/webdavfs/archive/webdavfs-389.tar.gz