Subtitles finder 1.04
VLC Extensions
Score 62%
Description:

Get the subtitles of movies from the internet, currently only from OpenSubtitles.org

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

Salem

11 months ago

thanks

Report

romancos

3 years ago

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).

Report

vfikov

3 years ago

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?

Report

qwerty1234

4 years ago

is it possible to add a language (hebrew) to the extension? maybe in the script?

Report

cipricus

4 years ago

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

Report

thepanz

4 years ago

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! :)

Report

cipricus

4 years ago

is it not possible to have it on VLC-addons.org?

Report

mederi

4 years ago

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.

Report

cipricus

4 years ago

why are so many extensions outdated/abandoned? who can post extensions here? are there other websites with vlc extensions?

Report

cipricus

4 years ago

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?

Report

cipricus

4 years ago

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)

Report

XweAponX

4 years ago

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!

Report

mangeanna

5 years ago

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.

Report

dmachop

5 years ago

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?

Report

thomaslaas

5 years ago

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 :)

Report

Pataglu

5 years ago

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("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;", 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" }
}"

Report

thomaslaas

5 years ago

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 :)

Report

Pataglu

5 years ago

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 ?

Report

thomaslaas

5 years ago

Ok now you have to just copy that file to your C:Program Files/VideoLAN/VLC/lua/playlist.

Report

Pataglu

5 years ago

Thanks again for your help !
I found the folder on MAC.
The path is : content/MacOs/share/lua/playlist

Report

Pataglu

5 years ago

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 ?

Report

w0q

4 years ago

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.

Report

fillemazendacus

4 years ago

Right place will be:
/usr/lib/vlc/lua/extensions/

Report

w0q

4 years ago

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.

Report

Pataglu

5 years ago

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("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;", 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" }
}"

Report

File (click to download) Version Description Filetype Packagetype License Downloads Date Filesize OCS-Install DL
Details
version
updated May 15 2011
added May 15 2011
downloads today
5
page views today 28