Created
May 24, 2026 04:54
-
-
Save Backsoon0/0d19a1c00ff210a95261cb94d4b4a3fb to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| -- tc2sc_sub.lua | |
| -- 快捷键: Ctrl+t | |
| -- 依赖: opencc (必须), ffmpeg (仅提取内封字幕时需要) | |
| local mp = require 'mp' | |
| local utils = require 'mp.utils' | |
| local msg = require 'mp.msg' | |
| -- OpenCC 配置文件,默认为繁转简 (Traditional to Simplified) | |
| local OPENCC_CONFIG = "t2s.json" | |
| -- 获取文件扩展名 | |
| local function get_extension(path) | |
| return path:match("^.+(%..+)$") or "" | |
| end | |
| -- 获取去除了扩展名的文件名 | |
| local function strip_extension(path) | |
| return path:match("^(.+)%..+$") or path | |
| end | |
| -- 核心转换函数 | |
| local function convert_sub() | |
| local sid = mp.get_property_number("sid") | |
| if not sid then | |
| mp.osd_message("没有选择任何字幕 (No subtitle selected)") | |
| return | |
| end | |
| local track_list = mp.get_property_native("track-list") | |
| local current_sub = nil | |
| -- 找到当前的字幕轨道 | |
| for _, track in ipairs(track_list) do | |
| if track.type == "sub" and track.id == sid then | |
| current_sub = track | |
| break | |
| end | |
| end | |
| if not current_sub then | |
| mp.osd_message("未找到字幕轨道信息") | |
| return | |
| end | |
| local is_external = current_sub.external | |
| local in_file = current_sub["external-filename"] | |
| local out_file = "" | |
| local video_path = mp.get_property("path") | |
| local dir, filename = utils.split_path(video_path) | |
| if is_external and in_file then | |
| -- ========== 处理外封字幕 ========== | |
| local in_dir, in_name = utils.split_path(in_file) | |
| local base_name = strip_extension(in_name) | |
| local ext = get_extension(in_name) | |
| -- 重命名逻辑:将 .tc 或 .TC 替换为 .tc2sc,如果没有则直接追加 .tc2sc | |
| if string.match(base_name:lower(), "%.tc$") then | |
| base_name = string.gsub(base_name, "%.tc$", ".tc2sc") | |
| base_name = string.gsub(base_name, "%.TC$", ".tc2sc") | |
| else | |
| base_name = base_name .. ".tc2sc" | |
| end | |
| out_file = utils.join_path(in_dir, base_name .. ext) | |
| mp.osd_message("正在使用 OpenCC 转换外封字幕...") | |
| run_opencc(in_file, out_file) | |
| else | |
| -- ========== 处理内封字幕 ========== | |
| local ff_index = current_sub["ff-index"] | |
| if not ff_index then | |
| mp.osd_message("无法获取内封字幕的流索引") | |
| return | |
| end | |
| -- 判断字幕格式 (ASS 或 SRT) | |
| local codec = current_sub["codec"] | |
| local ext = ".ass" | |
| if codec == "subrip" then ext = ".srt" end | |
| local base_video_name = strip_extension(filename) | |
| -- 临时文件和输出文件路径 | |
| local temp_file = utils.join_path(dir, base_video_name .. "_track_" .. tostring(sid) .. "_temp" .. ext) | |
| out_file = utils.join_path(dir, base_video_name .. ".tc2sc" .. ext) | |
| mp.osd_message("正在使用 FFmpeg 提取内封字幕...") | |
| -- 步骤1: 用 FFmpeg 提取字幕 | |
| local ext_res = mp.command_native({ | |
| name = "subprocess", | |
| playback_only = false, | |
| capture_stdout = true, | |
| capture_stderr = true, | |
| args = {"ffmpeg", "-y", "-i", video_path, "-map", "0:" .. tostring(ff_index), "-c:s", "copy", temp_file} | |
| }) | |
| if ext_res.status ~= 0 then | |
| mp.osd_message("提取内封字幕失败!(请确保已安装 FFmpeg)") | |
| msg.error("FFmpeg error: " .. (ext_res.stderr or "")) | |
| return | |
| end | |
| mp.osd_message("正在使用 OpenCC 转换内封字幕...") | |
| -- 步骤2: 用 OpenCC 转换 | |
| run_opencc(temp_file, out_file) | |
| -- 步骤3: 清理提取出的临时文件 | |
| os.remove(temp_file) | |
| end | |
| end | |
| -- 调用 OpenCC 执行转换并加载字幕 | |
| function run_opencc(in_file, out_file) | |
| local res = mp.command_native({ | |
| name = "subprocess", | |
| playback_only = false, | |
| capture_stdout = true, | |
| capture_stderr = true, | |
| args = {"opencc", "-i", in_file, "-o", out_file, "-c", OPENCC_CONFIG} | |
| }) | |
| if res.status == 0 then | |
| mp.osd_message("繁简转换成功!已加载新字幕。") | |
| -- 挂载新生成的字幕并选中它 ("select" 标志表示立即切换过去) | |
| mp.commandv("sub-add", out_file, "select") | |
| else | |
| mp.osd_message("OpenCC 转换失败!(请确保 opencc 在系统变量中)") | |
| msg.error("OpenCC error: " .. (res.stderr or "")) | |
| end | |
| end | |
| -- 绑定快捷键 Ctrl+T | |
| mp.add_key_binding("ctrl+t", "convert_sub_t2s", convert_sub) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment