(Based on the script made by Jean-Philippe André

How to install and use:
1) Install VLC
2) Place the script in:
- Windows (all users): %ProgramFiles%VideoLANVLCluaextensions
- Windows (current user): %APPDATA%VLCluaextensions
- Linux (all users): /usr/share/vlc/lua/extensions/
- Linux (current user): ~/.local/share/vlc/lua/extensions/
- Mac OS X (all users): /Applications/VLC.app/Contents/MacOS/share/lua/extensions/
- Mac OS X (current user): ~/Library/Application Support/org.videolan.vlc/lua/extensions/
Ratings & Comments
42 Comments
thanks
I can search subtitles but wjhenever I try to download I get error message with some bizzarre path to the file. VLC could not open the file "/home/roman/zip://http://www.opensubtitles.org/en/http://dl.opensubtitles.org/en/download/subad/5850439!/Arrow.S03E01.HDTV.x264?2dLOL.srt" (No such file or directory).
The plugin successfully finds the subs, but when I click the load button - every time I get the 'Kill now..' dialog. I'm on linux, vlc-2.1.4(i tested on older ver but it was the same) Any suggestions?
it's exactly the same in 2021, 6 years later. Just switched player
is it possible to add a language (hebrew) to the extension? maybe in the script?
the script from here - http://forum.videolan.org/viewtopic.php?f=29&t=71535&p=370875#p370875 - was updated and now works in both Windows and Linux. also, this version doesn't need 'View/Subtitle' Finder be clicked twice
The script on my repository (http://thepanz.netsons.org/post/vlc-and-opensubtitles-downloader) has been updated with latest changes :) Thanks all for your efforts! :)
is it not possible to have it on VLC-addons.org?
Right! It is a mess; obsolete version here, updated versions there and there. http://addons.videolan.org is the right place for VLC Extensions. ale5000 seems to be inactive. thepanz has no access here to upload his updates.
why are so many extensions outdated/abandoned? who can post extensions here? are there other websites with vlc extensions?
I would like to have a subtitle file once and for good. While the script says ‘Download subtitles’, I imagine they are downloaded temporarily during playback: where are they downloaded? can I manually save/safekeep them for future use?
for Linux: http://pastebin.com/HqLncjdc); may be downloaded as .lua here (https://docs.google.com/file/d/0B35PbjeIaccqcEF2ZlhEY2FuRHM/edit). solution privided by askubuntu user here (http://askubuntu.com/a/267726/47206) for windows: http://forum.videolan.org/viewtopic.php?f=29&t=71535&p=370875#p370875. (may be downloaded as .lua here: https://docs.google.com/file/d/0B35PbjeIaccqWVQ3UW5LekoyYUE/edit?usp=sharing)
The last time I visited this page, there was a download link for a windows installer for this someone made. I've used this and it works rather well, as long as the media I'm viewing is relatively new. Was that link here, or was it in the thread over on the VLC site? Thanx!
how to find subtitles.....i did everything unto copying files to that folder...now i am in vlc player so how do i can search the subtitles.
VLC can't recognize the input's format: The format of 'http://www.opensubtitles.org/en/http://dl.opensubtitles.org/en/download/subad/xxxxxxx cannot be detected. Have a look at the log for details. OS: Fedora 16 The link actually gives a .zip file. Any workaround?
All you have to do is copy everything on that page, put it into a text file but save it as a luac file. It worked for me :)
I'm stuck at the very begining of the processus : I just can't download any file. When I click on the download button I have a page with text on it and I have no idea what I should do with it. "--[[ Subtitles Copyright © 2009-2011 VideoLAN and AUTHORS Authors: ale5000 (Based on the script made by Jean-Philippe André) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. --]] --[[ Notes - Because of internal changes in VLC, the minimum version of VLC required is now: 1.1.0 git - 2010-03-21 - VLC support only uncompressed .rar files Know issues - The search fail if you click the button two times consecutively Changelog 1.04 - Updated for the latest GIT build (now almost all lua bugs are fixed) - Bumped the minimum version required - Minor changes 1.03 - Fixed the duplicated names that were appearing in the search - Fixed the empty names that were appearing in the search - Now there is a message when it doesn't find anything - Minor optimizations - Minor fixes 1.02 - Fix for the latest GIT build 1.01 - Changed version schema - Now there isn't any dialog showed by default, you can still open them from the menu - Now it is more clear when the script is working - Added some dlg:flush() that were missing (this fix the elements in the dialog that weren't updated) - Now it catch the fail of vlc.stream - Minor fixes 0.1.8 - Now you can open a new dialog while the previous is still open - Fixed getting title in the new version of VLC - Now using dlg:flush() where appropriate - Workarounded some bugs in VLC IMPORTANT: Now it no longer work on old versions of VLC 0.1.7 - Removed the button "+"; it is useless since the title is updated automatically - The download dialog can now be hidden/showed - Added the "Load from url..." dialog - The code of parse_archive() is now a separate function called by both "Load from url..." and the normal subtitles download dialog. - Minor changes 0.1.6 - Some variables made local - Minor fixes - Added .rar archive support ("stream_filter_rar" is incomplete and can only use one file in the archive, need a fix in VLC) Note: VLC support only uncompressed .rar files ]] -- Global variables dlg = nil dialog_is_opened = false dialog_is_hidden = false update_title_needed = false -- -Common website = nil language = nil main_text_input = nil search_button = nil load_button = nil -- -Dialog "Download subtitles" subtitles_list = nil subtitles_result = nil -- -Dialog "Load subtitles from url..." type_text_input = nil function descriptor() return { title = "Subtitles"; version = "1.04"; author = "ale5000"; url = 'http://ale5000.altervista.org/vlc/extensions/subtitles-mod.lua'; description = "<center><b>Subtitles</b></center>" .. "Get the subtitles of movies from the internet, currently only from OpenSubtitles.org<br /><br />" .. "<img src='http://static.opensubtitles.org/favicon.ico' /> Subtitles service allowed by <a href='http://www.opensubtitles.org/'>www.OpenSubtitles.org</a><br />" .. "<br /><b>(Based on the script made by Jean-Philippe André)</b>"; shortdesc = "Get the subtitles of movies from the internet, currently only from OpenSubtitles.org"; capabilities = { "menu"; "input-listener"--[[; "meta-listener"]] } } end function menu() if not dialog_is_hidden then return { "Download", "Upload", "Load from url...", "About" } else return { "Show" } end end -- Function triggered when the extension is activated function activate() vlc.msg.dbg(_VERSION) vlc.msg.dbg("[Subtitles] Activating") trigger_menu(1) return true end -- Function triggered when the extension is deactivated function deactivate() if dialog_is_opened then close() else reset_variables() dlg = nil end vlc.msg.dbg("[Subtitles] Deactivated") return true end function reset_variables() update_title_needed = false -- Common website = nil language = nil main_text_input = nil search_button = nil load_button = nil -- Dialog "Download subtitles" subtitles_list = nil subtitles_result = nil -- Dialog "Load subtitles from url..." type_text_input = nil end -- Function triggered when the dialog is closed function close() dialog_is_opened = false dialog_is_hidden = false vlc.msg.dbg("[Subtitles] Closing dialog") reset_variables() if dlg ~= nil then dlg:delete() end dlg = nil return true end -- Current input changed function input_changed() vlc.msg.dbg("[Subtitles] Input is changed") update_title() end -- Current input item meta changed --[[function meta_changed() end]] function update_title() if dialog_is_hidden or not update_title_needed then return true end vlc.msg.dbg("[Subtitles] Updating title") local item = vlc.input.item() if item == nil then return false end local title = item:name() -- It return the internal title or the filename if the first is missing if title ~= nil then title = string.gsub(title, "(.*)%.%w+$", "%1") -- Removes file extension if title ~= "" then main_text_input:set_text(title) dlg:update() return true end end return false end function show_dialog_download() -- column, row, colspan, rowspan dlg:add_label("<right><b>Database: </b></right>", 1, 1, 1, 1) website = dlg:add_dropdown(2, 1, 3, 1) dlg:add_label("<right><b>Language: </b></right>", 1, 2, 1, 1) language = dlg:add_dropdown(2, 2, 3, 1) dlg:add_label("<right><b>Search: </b></right>", 1, 3, 1, 1) main_text_input = dlg:add_text_input("", 2, 3, 1, 1) search_button = dlg:add_button("Search", click_search, 3, 3, 1, 1) dlg:add_button("Hide", hide_dialog, 4, 3, 1, 1) for idx, ws in ipairs(websites) do website:add_value(ws.title, idx) end for idx, ws in ipairs(languages) do language:add_value(ws.title, idx) end update_title_needed = true update_title() dlg:update() return true end function show_dialog_upload() -- column, row, colspan, rowspan dlg:add_label("<right><b>Database: </b></right>", 1, 1, 1, 1) website = dlg:add_dropdown(2, 1, 4, 1) -- FIXME: Link is NOT yet working dlg:add_label("<center><a href='http://www.opensubtitles.org/upload'>Upload to OpenSubtitles.org</a></center>", 1, 2, 2, 1) for idx, ws in ipairs(websites) do website:add_value(ws.title, idx) end dlg:update() return true end function show_dialog_load_url() -- column, row, colspan, rowspan dlg:add_label("<right><b>URL: </b></right>", 1, 1, 1, 1) main_text_input = dlg:add_text_input("", 2, 1, 3, 1) dlg:add_label("<right><b>Type: </b></right>", 1, 2, 1, 1) type_text_input = dlg:add_text_input("", 2, 2, 1, 1) dlg:add_label(" ", 3, 2, 1, 1) -- Spacer load_button = dlg:add_button("Load", click_load_from_url_button, 4, 2, 1, 1) dlg:update() return true end function show_dialog_about() local data = descriptor() -- column, row, colspan, rowspan dlg:add_label("<center><b>" .. data.title .. " " .. data.version .. "</b></center>", 1, 1, 1, 1) dlg:add_html(data.description, 1, 2, 1, 1) dlg:update() return true end function sleep(sec) local t = vlc.misc.mdate() vlc.misc.mwait(t + sec*1000*1000) end function new_dialog(title) dlg = vlc.dialog(title) end function hide_dialog() dialog_is_hidden = true dlg:hide() end -- Function triggered when a element from the menu is selected function trigger_menu(id) if dialog_is_hidden then if dlg == nil then vlc.msg.err("[Subtitles] Dialog pointer lost") close() return false; end dialog_is_hidden = false dlg:show() return true end if(dialog_is_opened) then close() end dialog_is_opened = true if id == 1 then new_dialog("Download subtitles") return show_dialog_download() elseif id == 2 then new_dialog("Upload subtitles") return show_dialog_upload() elseif id == 3 then new_dialog("Load subtitles from url...") return show_dialog_load_url() elseif id == 4 then new_dialog("About") return show_dialog_about() end vlc.msg.err("[Subtitles] Invalid menu id: "..id) return false end function click_search() vlc.msg.dbg("[Subtitles] Clicked search button from \"Download subtitles\" dialog") local search_term = main_text_input:get_text() if(search_term == "") then return false end local old_button_name = search_button:get_text() search_button:set_text("Wait...") if subtitles_list ~= nil then subtitles_list:clear() end dlg:update() subtitles_result = nil local idx = website:get_value() local idx2 = language:get_value() if idx < 1 or idx2 < 1 then vlc.msg.err("[Subtitles] Invalid index in dropdown") search_button:set_text(old_button_name) return false end local ws = websites[idx] local lang = languages[idx2] local url = ws.urlfunc(search_term) -- vlc.msg.info("[Subtitles] Url: '" .. url .. "'") local stream = vlc.stream(url) if stream == nil then vlc.msg.err("[Subtitles] The site of subtitles isn't reachable") search_button:set_text(old_button_name) return false end local reading = "blah" local xmlpage = "" while(reading ~= nil and reading ~= "") do reading = stream:read(65653) if(reading) then xmlpage = xmlpage .. reading end end if xmlpage == "" then search_button:set_text(old_button_name) return false end subtitles_result = ws.parsefunc(xmlpage) if subtitles_list == nil then subtitles_list = dlg:add_list(1, 4, 4, 1) load_button = dlg:add_button("Load selected subtitles", click_load_from_search_button, 1, 5, 4, 1) end if not subtitles_result then subtitles_result = {} subtitles_result[1]= { url = "-1" } subtitles_list:add_value("Nothing found", 1) search_button:set_text(old_button_name) dlg:update() return false end for idx, res in ipairs(subtitles_result) do if(not res.language or lang.tag == "all" or lang.tag == res.language) then subtitles_list:add_value("["..res.language.."] "..res.name, idx) end end search_button:set_text(old_button_name) dlg:update() return true end function load_unknown_subtitles(url, language) vlc.msg.dbg("[Subtitles] Loading "..language.." subtitle: "..url) vlc.input.add_subtitle(url) end function load_subtitles_in_the_archive(dataBuffer, language) local buffer_length = dataBuffer:len() local files_found_in_the_compressed_file = 0 local subtitles_found_in_the_compressed_file = 0 local endIdx = 1 local srturl, extension -- Find subtitles while(endIdx < buffer_length) do _, endIdx, srturl, extension = dataBuffer:find("<location>([^<]+)%.(%a%a%a?)</location>", endIdx) if(srturl == nil ) then break end --vlc.msg.dbg("[Subtitles] File found in the archive: " .. srturl .. extension) files_found_in_the_compressed_file = files_found_in_the_compressed_file + 1 srturl = string.gsub(srturl, "^(%a%a%a)://", "%1://http://") if(extension == "ass" or extension == "ssa" or extension == "srt" or extension == "smi" or extension == "sub" or extension == "rt" or extension == "txt" or extension == "mpl") then subtitles_found_in_the_compressed_file = subtitles_found_in_the_compressed_file + 1 vlc.msg.dbg("[Subtitles] Loading "..language.." subtitle: "..srturl) vlc.input.add_subtitle(srturl.."."..extension) end end vlc.msg.info("[Subtitles] Files found in the compressed file: "..files_found_in_the_compressed_file) vlc.msg.info("[Subtitles] Subtitles found in the compressed file: "..subtitles_found_in_the_compressed_file) if(subtitles_found_in_the_compressed_file > 0) then return true end vlc.msg.warn("[Subtitles] No subtitles found in the compressed file") return false end function parse_archive(url, language) if url == "-1" then vlc.msg.dbg("[Subtitles] Dummy result") return true end local stream = vlc.stream(url) if stream == nil then vlc.msg.err("[Subtitles] The site of subtitles isn't reachable") return false end stream:addfilter("zip,stream_filter_rar") local data = stream:read(2048) if(data == nil or data:find("<?xml version", 1, true) ~= 1) then vlc.msg.info("[Subtitles] Type: RAR or unknown file") load_unknown_subtitles(url, language) else vlc.msg.info("[Subtitles] Type: ZIP file") local dataBuffer = "" while(data ~= nil and data ~= "") do vlc.msg.dbg("Buffering...") dataBuffer = dataBuffer..data data = stream:read(8192) end load_subtitles_in_the_archive(dataBuffer, language) end --vlc.msg.dbg("[Subtitles] Subtitle data: "..dataBuffer) return true end function click_load_from_search_button() vlc.msg.dbg("[Subtitles] Clicked load button from \"Download subtitles\" dialog") if(not vlc.input.is_playing()) then vlc.msg.warn("[Subtitles] You cannot load subtitles if you aren't playing any file") return true end local old_button_name = load_button:get_text() load_button:set_text("Wait...") dlg:update() local selection = subtitles_list:get_selection() local index, name for index, name in pairs(selection) do vlc.msg.dbg("[Subtitles] Selected the item "..index.." with the name: "..name) vlc.msg.dbg("[Subtitles] URL: "..subtitles_result[index].url) parse_archive(subtitles_result[index].url, subtitles_result[index].language) -- ZIP, RAR or unknown file end load_button:set_text(old_button_name) dlg:update() return true end function click_load_from_url_button() vlc.msg.dbg("[Subtitles] Clicked load button in \"Load subtitles from url...\" dialog") if(not vlc.input.is_playing()) then vlc.msg.warn("[Subtitles] You cannot load subtitles if you aren't playing any file") return true end local old_button_name = load_button:get_text() load_button:set_text("Wait...") type_text_input:set_text("") dlg:update() local url_to_load = main_text_input:get_text() if(url_to_load == "") then return false end vlc.msg.dbg("[Subtitles] URL: "..url_to_load) local _, ext_pos, extension = url_to_load:find("%.(%a%a%a?)", -4) if(ext_pos == url_to_load:len()) then type_text_input:set_text(extension) if(extension == "ass" or extension == "ssa" or extension == "srt" or extension == "smi" or extension == "sub" or extension == "rt" or extension == "txt" or extension == "mpl") then load_button:set_text(old_button_name) dlg:update() return vlc.input.add_subtitle(url_to_load) end end local result = parse_archive(url_to_load, "") if not result then vlc.msg.info("[Subtitles] Waiting 5 seconds before retry...") sleep(5) result = parse_archive(url_to_load, "") end load_button:set_text(old_button_name) dlg:update() return result end -- XML Parsing function parseargs(s) local arg = {} string.gsub(s, "(%w+)=([\"'])(.-)%2", function (w, _, a) arg[w] = a end) return arg end function collect(s) local stack = {} local top = {} table.insert(stack, top) local ni,c,label,xarg, empty local i, j = 1, 1 while true do ni,j,c,label,xarg, empty = string.find(s, "<(%/?)([%w:]+)(.-)(%/?)>", i) if not ni then break end local text = string.sub(s, i, ni-1) if not string.find(text, "^%s*$") then table.insert(top, text) end if empty == "/" then -- empty element tag table.insert(top, {label=label, xarg=parseargs(xarg), empty=1}) elseif c == "" then -- start tag top = {label=label, xarg=parseargs(xarg)} table.insert(stack, top) -- new level else -- end tag local toclose = table.remove(stack) -- remove top top = stack[#stack] if #stack < 1 then error("nothing to close with "..label) end if toclose.label ~= label then error("trying to close "..toclose.label.." with "..label) end table.insert(top, toclose) end i = j+1 end local text = string.sub(s, i) if not string.find(text, "^%s*$") then table.insert(stack[#stack], text) end if #stack > 1 then error("unclosed "..stack[stack.n].label) end return stack[1] end --[[ Websites configurations ]]-- -- OpenSubtitles.org -- This function uses first version of OS API. It will probably fail in -- the future. We'll need a XML-RPC key btw function urlOpenSub(search_term) -- base = "http://api.opensubtitles.org/xml-rpc" -- lang = "eng" base = "http://api.opensubtitles.org/en/search/" -- if(lang) then base = base .. "sublanguageid-" .. lang .. "/" search_term = string.gsub(search_term, "%%", "%%37") search_term = string.gsub(search_term, " ", "%%20") return base .. "moviename-" .. search_term .. "/simplexml" -- http://api.opensubtitles.org/en/search/moviename- .. search_term .. /simplexml end function parseOpenSub(xmltext) vlc.msg.dbg("[Subtitles] Parsing XML data...") local xmltext = string.gsub(xmltext, "<%?xml version=\"1%.0\" encoding=\"utf-8\"%?>", "") local xmldata = collect(xmltext) for a,b in pairs(xmldata) do if type(b) == "table" then if b.label == "search" then xmldata = b break end end end if xmldata == nil then return nil end -- Subtitles information data local subname = {} local sub_movie = {} local suburl = {} local sublang = {} local sub_language = {} local subformat = {} local subfilenum = {} local subnum = 1 local baseurl = "" -- Let's browse iteratively the 'xmldata' tree -- OK, the variables' names aren't explicit enough, but just remember a couple -- a,b contains the index (a) and the data (b) of the table, which might also be a table for a,b in pairs(xmldata) do if type(b) == "table" then if b.label == "results" then for c,d in pairs(b) do if type(d) == "table" then if d.label == "subtitle" then for e,f in pairs(d) do if type(f) == "table" then if f.label == "releasename" then if f[1] ~= nil then subname[subnum] = f[1] else subname[subnum] = "" end elseif f.label == "movie" then if f[1] ~= nil then sub_movie[subnum] = f[1] else sub_movie[subnum] = "" end elseif f.label == "download" then if f[1] ~= nil then suburl[subnum] = f[1] else suburl[subnum] = "" end elseif f.label == "iso639" then -- language if f[1] ~= nil then sublang[subnum] = f[1] else sublang[subnum] = "" end elseif f.label == "language" then -- language -- not use yet if f[1] ~= nil then sub_language[subnum] = f[1] else sub_language[subnum] = "" end elseif f.label == "format" then if f[1] ~= nil then subformat[subnum] = f[1] else subformat[subnum] = "" end end end end subnum = subnum + 1 end end end elseif b.label == "base" then baseurl = b[1] end end end if subnum <= 1 then return nil end ret = {} for i = 1,(subnum - 1) do fullURL = baseurl .. "/" .. suburl[i] realName = string.gsub( subname[i], "<..CDATA.", "" ) realName = string.gsub( realName, "..>", "" ) if realName == "" then realName = string.gsub( sub_movie[i], "<..CDATA.", "" ) realName = string.gsub( realName, "..>", "" ) end ret[i] = { name = realName, url = fullURL, language = sublang[i], extension = ".zip" } vlc.msg.dbg("[Subtitles] Found subtitle " .. i .. ": ") vlc.msg.dbg(realName) vlc.msg.dbg(fullURL) end return ret end -- These tables must be after all function definitions websites = { { title = "OpenSubtitles.org", urlfunc = urlOpenSub, parsefunc = parseOpenSub } --[[; { title = "Fake (OS)", urlfunc = url2, parsefunc = parse2 }]] } languages = { { title = "All", tag = "all" }, { title = "English", tag = "en" }, { title = "Chinese", tag = "zh" }, { title = "Finnish", tag = "fi" }, { title = "French", tag = "fr" }, { title = "German", tag = "de" }, { title = "Italian", tag = "it" }, { title = "Japanese", tag = "ja" }, { title = "Polish", tag = "pl" }, { title = "Portuguese", tag = "pt" }, { title = "Russian", tag = "ru" }, { title = "Spanish", tag = "es" } }"
All you have to do is copy everything on that page, put it into a text file but save it as a luac file. It worked for me :)
Thanks for your help. Yet I'm not successful : What do I do after the creating the .luac ? I cannot open it with vlc. Should I copy it somewhere ?
Ok now you have to just copy that file to your C:Program Files/VideoLAN/VLC/lua/playlist.
Thanks again for your help ! I found the folder on MAC. The path is : content/MacOs/share/lua/playlist
Ok, I hope this will be my last question : How do I use it once it's in the right folder ? I open a movie in VLC, and then ? How to find the subtitles ?
I'm on Linux, Ubuntu. What do I do? I tried creating file subtitles-mod.lua in /usr/share/vlc/lua and then in /usr/share/vlc/lua/http and then also /usr/share/vlc/lua/playlist. It didn't work = I played video in VLC and didn't find anything new under rigth-click/View. Thanks.
Right place will be: /usr/lib/vlc/lua/extensions/
Thanks! It worked. I just copied the code into the file Quote:/usr/lib/vlc/lua/extensions/subtitles-mod.luac that I created.
Now, right-click/View/Subtitles opens a little window with subtitels searcher. The experience of using this not that much more comfortable than going to a browser and googling and downloading I'm afraid.