dotfiles

My personal dotfiles
git clone git://pcardensab.com/dotfiles
Log | Files | Refs | Submodules | README

vtt.lua (5300B)


      1 local mp = require 'mp'
      2 
      3 local function convert_vtt_subtitles()
      4     local sid = mp.get_property_native("sid")
      5     local tracks = mp.get_property_native("track-list")
      6     local current_subtitle_track
      7 
      8     if sid and sid ~= "no" then
      9         for _, track in ipairs(tracks) do
     10             if track["type"] == "sub" and track.id == sid then
     11                 current_subtitle_track = track
     12                 break
     13             end
     14         end
     15     end
     16     if not current_subtitle_track then
     17         mp.osd_message("No selected subtitle track")
     18         return
     19     end
     20 
     21     local path = current_subtitle_track["external-filename"]
     22     if not current_subtitle_track.external or not path or not (path:match("%.vtt$") or path:match("^edl://")) then
     23         mp.osd_message("Selected subtitle is not an external VTT")
     24         return
     25     end
     26 
     27     if path:match("^edl://") then
     28         local body = path:sub(7)
     29         local url
     30 
     31         -- ytdl_hook adds subtitles as EDL with the real URL in a
     32         -- length-prefixed segment after the delay_open headers.
     33         for entry in body:gmatch("[^;]+") do
     34             if not entry:match("^!") then
     35                 local len, value = entry:match("^%%(%d+)%%(.*)")
     36 
     37                 if len then
     38                     url = value:sub(1, tonumber(len))
     39                 else
     40                     url = entry:match("^[^,]+")
     41                 end
     42 
     43                 break
     44             end
     45         end
     46 
     47         if url then
     48             if url:match("[?&]fmt=") then
     49                 url = url:gsub("([?&])fmt=[^&]*", "%1fmt=vtt")
     50             elseif url:match("%?") then
     51                 url = url .. "&fmt=vtt"
     52             else
     53                 url = url .. "?fmt=vtt"
     54             end
     55 
     56             local res = mp.command_native({
     57                 name = "subprocess",
     58                 args = {"curl", "-L", "-s", url},
     59                 capture_stdout = true,
     60                 capture_stderr = true,
     61             })
     62 
     63             if not res or res.status ~= 0 or res.stdout == "" then
     64                 mp.msg.warn("Could not download VTT subtitle")
     65                 return
     66             end
     67 
     68             path = os.tmpname() .. ".vtt"
     69             local file_vtt = io.open(path, "w")
     70             file_vtt:write(res.stdout)
     71             file_vtt:close()
     72         else
     73             path = nil
     74         end
     75     end
     76 
     77     local f = path and io.open(path, "r")
     78     if not f then
     79         mp.msg.warn("Could not open VTT subtitle")
     80         return
     81     end
     82 
     83     local path_new = os.tmpname() .. ".srt"
     84     local file_new = io.open(path_new, 'w')
     85     local path_sentences = os.tmpname() .. ".srt"
     86     local file_sentences = io.open(path_sentences, 'w')
     87 
     88     local str_start
     89     local str_end
     90     local index = 1
     91     local index_sentence = 1
     92     local i_line = 0
     93     local sentence = {}
     94     local previous_timestamp_sentence = "00:00:00.000"
     95     for line in f:lines() do
     96         if i_line % 8 == 4 then
     97             str_start, str_end = line:match("(%d%d:%d%d:%d%d%.%d+)%s+-->%s+(%d%d:%d%d:%d%d%.%d+)")
     98         end
     99         if i_line % 8 == 6 then
    100             local line = line
    101 
    102             -- remove <c> tags
    103             line = line:gsub("</?c>", "")
    104 
    105             -- prepend start time
    106             line = " " .. line .. "<" .. str_end .. ">"
    107 
    108             local previous_timestamp = str_start
    109             for content, timestamp in line:gmatch("([^<]*)<(%d%d:%d%d:%d%d%.%d+)>") do
    110                 local word = content:gsub("&gt;", ">"):gsub("&nbsp;", " ")
    111 
    112                 file_new:write(index, '\n')
    113                 file_new:write(previous_timestamp .. " --> " .. timestamp, '\n')
    114                 file_new:write(word, '\n')
    115                 file_new:write('\n')
    116 
    117                 if word:sub(1, 3) == " >>" then
    118                     file_sentences:write(index_sentence, '\n')
    119                     file_sentences:write(previous_timestamp_sentence .. " --> " .. previous_timestamp, '\n')
    120                     file_sentences:write(table.concat(sentence), '\n')
    121                     file_sentences:write('\n')
    122                     index_sentence = index_sentence + 1
    123                     previous_timestamp_sentence = previous_timestamp
    124                     sentence = {}
    125                 end
    126 
    127                 table.insert(sentence, word)
    128 
    129                 if word:sub(-1) == "." or word:sub(-1) == "?" or word:sub(-1) == ":" or word:sub(-2) == ".\"" or word:sub(-2) == "?\"" then
    130                     file_sentences:write(index_sentence, '\n')
    131                     file_sentences:write(previous_timestamp_sentence .. " --> " .. timestamp, '\n')
    132                     file_sentences:write(table.concat(sentence), '\n')
    133                     file_sentences:write('\n')
    134                     index_sentence = index_sentence + 1
    135                     previous_timestamp_sentence = timestamp
    136                     sentence = {}
    137                 end
    138 
    139                 previous_timestamp = timestamp
    140                 index = index + 1
    141             end
    142         end
    143         i_line = i_line + 1
    144     end
    145     file_new:close()
    146     file_sentences:close()
    147     f:close()
    148 
    149     mp.commandv("sub-add", path_new, "select")
    150     mp.commandv("sub-add", path_sentences, "select")
    151 
    152     mp.osd_message("Loaded converted VTT subtitles")
    153     mp.msg.info("Loaded converted VTT subtitles")
    154 end
    155 
    156 mp.add_key_binding(nil, "convert-vtt", convert_vtt_subtitles)
    157 
    158 -- vim: sts=4 sw=4 et