射手影音最近做了一件很有争议的事情:将SPlayerX摆上了Mac AppStore。SPlayerX是一个Fork自MPleryX的影音播放器。这次射手为了完全规避GPL协议的限制,将字幕下载部分功能用二进制可执行程序方式释出,以fork运行的方式调用这个名为sscl的二进制文件下载字幕。
姑且不论其将二进制文件与GPL协议软件捆绑发行是否违反GPL协议以及GPL协议软件与Mac AppStore的协议是否有冲突via。射手这次的做法恰好为所有Mac用户送上了sscl这个大礼,可以使用这个工具自动匹配本地硬盘的视频文件。
原来的设想是用AppleScript写一个脚本,并在Finder里自动监控特定目录,这样每当某目录下有新视频文件添加时就会自动下载字幕。但是我对AppleScript实在不熟悉,加上相关参考资料太少,遂作罢用bash写了一个脚本。如果有AppleScript高手,请改写之:-)
果然抛砖引玉,请参考利用Hazel让Mac自动下载电影字幕更加自动化进行字幕下载操作:-)
sscl的字幕下载目的目录是固定的,所以脚本里就直接Hardcode进去了。
注意: 射手影音并没有为sscl单独设置一个license,我只能根据SPlayerX本身免费下载认为它是freeware。提取该文件单独运行引起的版权上的争议不在本文讨论范围内。 本文中提到的find、mktemp为GNU findutils和GNU coreutils里的版本,请通过MacPort或其他Port系统安装之后再执行
功能描述 执行脚本时,在预设的目录内查找mkv和avi文件,过滤掉某些0day release里的sample文件。 对于每个文件,如果不存在对应的.chn.srt字幕文件,就调用sscl进行下载并复制到电影文件所在文件夹。
使用方法
- 下载sscl文件。该文件可以从SPlayer Mercurial源里获取,地址是:http://hg.splayer.org/splayerx/raw/0b9e84441210/binaries/x86_64/sscl
- 修改该文件权限,终端下
chmod +x sscl
- 将以下代码保存为
sub.sh
。请根据你系统内的bash
路径修改shabang
,我的系统bash
是在/Users/yegle/Gentoo/bin/bash
的,一般的mac系统应该是在/bin/bash
。同时还要修改SSCL
变量为你系统内sscl
二进制文件路径,以及MOVIE_DIR
你的电影文件所在路径。 - 在终端下执行
sh sub.sh
,即可自动匹配你的MOVIE_DIR
目录下所有电影文件并自动将字幕复制到你的电影文件所在文件夹。如果有字幕没有下载到,将会在命令行里提示某个视频没有找到对应字幕。
脚本
#!/Users/yegle/Gentoo/bin/bash MOVIE_DIR=/Users/yegle/Downloads/ MOVIE_LIST=$(mktemp) SSCL=/Users/yegle/sscl rm -rf "$HOME/Library/Application Support/SPlayerX/SVPSub/"* find $MOVIE_DIR -regextype posix-extended -iregex '.*\.(mkv|avi)$'|grep -iv sample >$MOVIE_LIST while read movie_file_path do movie_filename=$(basename "$movie_file_path") movie_path=$(dirname "$movie_file_path") if [ ! -e "${movie_file_path%.*}.chn.srt" ] then $SSCL --video-file "$movie_file_path" --pull >/dev/null 2>&1 ls "$HOME/Library/Application Support/SPlayerX/SVPSub/${movie_filename%.*}.chn.srt" >/dev/null 2>&1 \ && mv "$HOME/Library/Application Support/SPlayerX/SVPSub/${movie_filename%.*}".*.srt "$movie_path" \ || echo $movie_file_path subtitle not found fi done < $MOVIE_LIST
2011-06-23更新:重写了一个脚本,功能相同,但是使用的是Mac自带的find
和mktemp
,这样无论是否有GNU的find
和mktemp
安装,都能正常执行了
#!/bin/bash MOVIE_DIR="/Volumes/Macintosh HD/Movie" MOVIE_LIST=$(/usr/bin/mktemp -t sub) SSCL=/Users/yegle/sscl rm -rf "$HOME/Library/Application Support/SPlayerX/SVPSub/"* /usr/bin/find -E "${MOVIE_DIR}" -iregex '.*\.(avi|mkv)$' |grep -iv sample >$MOVIE_LIST while read movie_file_path do movie_filename=$(basename "$movie_file_path") movie_path=$(dirname "$movie_file_path") if [ ! -e "${movie_file_path%.*}.chn.srt" ] then $SSCL --video-file "$movie_file_path" --pull >/dev/null 2>&1 ls "$HOME/Library/Application Support/SPlayerX/SVPSub/${movie_filename%.*}.chn.srt" >/dev/null 2>&1 \ && mv "$HOME/Library/Application Support/SPlayerX/SVPSub/${movie_filename%.*}".*.srt "$movie_path" \ || echo $movie_file_path subtitle not found fi done < $MOVIE_LIST
2014-04-10更新:重写了一个Python版本,功能相同但是使用Python内置工具,应该比shell脚本方便
#!/usr/bin/env python # vim: set fileencoding=utf-8 ts=4 sw=4 tw=79 : from __future__ import (unicode_literals, absolute_import, division, print_function) import os import subprocess import shutil from glob import glob from os.path import exists, join, basename movie_dir = os.path.expanduser('~/Movie/') sscl = os.path.expanduser('~/sscl') base_args = [sscl, '--pull', '--video-file'] if __name__ == '__main__': for root, dirs, files in os.walk(movie_dir): for f in files: f_wo_ext, ext = os.path.splitext(f) if ext not in {'.mkv'} or 'sample' in f_wo_ext.lower(): continue filename_wo_ext = join(root, f_wo_ext) if (glob("%s*.srt" % filename_wo_ext) or glob("%s*.ass" % filename_wo_ext)): continue filename = join(root, f) try: result = subprocess.check_output( base_args + [filename], timeout=10) subs = set(result.decode('utf-8').strip().split('\n')) for sub in subs: if not exists(join(root, basename(sub))): shutil.move(sub, root) except subprocess.CalledProcessError as e: print("NOT FOUND: %s" % f) except subprocess.TimeoutExpired: print("TIMEOUT: %s" % f)
Comments !