]> git.sesse.net Git - vlc/blob - share/lua/playlist/youtube.lua
Cleanup lua script escape sequences for lua 5.2.
[vlc] / share / lua / playlist / youtube.lua
1 --[[
2  $Id$
3
4  Copyright © 2007-2011 the VideoLAN team
5
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  GNU General Public License for more details.
15
16  You should have received a copy of the GNU General Public License
17  along with this program; if not, write to the Free Software
18  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 --]]
20
21 -- Helper function to get a parameter's value in a URL
22 function get_url_param( url, name )
23     local _, _, res = string.find( url, "[&?]"..name.."=([^&]*)" )
24     return res
25 end
26
27 function get_arturl()
28     local iurl = get_url_param( vlc.path, "iurl" )
29     if iurl then
30         return iurl
31     end
32     local video_id = get_url_param( vlc.path, "v" )
33     if not video_id then
34         return nil
35     end
36     return "http://img.youtube.com/vi/"..video_id.."/default.jpg"
37 end
38
39 function get_prefres()
40     local prefres = -1
41     if vlc.var and vlc.var.inherit then
42         prefres = vlc.var.inherit(nil, "preferred-resolution")
43         if prefres == nil then
44             prefres = -1
45         end
46     end
47     return prefres
48 end
49
50 -- Probe function.
51 function probe()
52     if vlc.access ~= "http" and vlc.access ~= "https" then
53         return false
54     end
55     youtube_site = string.match( string.sub( vlc.path, 1, 8 ), "youtube" )
56     if not youtube_site then
57         -- FIXME we should be using a builtin list of known youtube websites
58         -- like "fr.youtube.com", "uk.youtube.com" etc..
59         youtube_site = string.find( vlc.path, ".youtube.com" )
60         if youtube_site == nil then
61             return false
62         end
63     end
64     return (  string.match( vlc.path, "/watch%?" ) -- the html page
65             or string.match( vlc.path, "/v/" ) -- video in swf player
66             or string.match( vlc.path, "/player2.swf" ) ) -- another player url
67 end
68
69 -- Parse function.
70 function parse()
71     if string.match( vlc.path, "/watch%?" )
72     then -- This is the HTML page's URL
73         -- fmt is the format of the video
74         -- (cf. http://en.wikipedia.org/wiki/YouTube#Quality_and_codecs)
75         fmt = get_url_param( vlc.path, "fmt" )
76         while true do
77             -- Try to find the video's title
78             line = vlc.readline()
79             if not line then break end
80             if string.match( line, "<meta name=\"title\"" ) then
81                 _,_,name = string.find( line, "content=\"(.-)\"" )
82                 name = vlc.strings.resolve_xml_special_chars( name )
83                 name = vlc.strings.resolve_xml_special_chars( name )
84             end
85             if string.match( line, "<meta name=\"description\"" ) then
86                -- Don't ask me why they double encode ...
87                 _,_,description = string.find( line, "content=\"(.-)\"" )
88                 description = vlc.strings.resolve_xml_special_chars( description )
89                 description = vlc.strings.resolve_xml_special_chars( description )
90             end
91             if string.match( line, "<meta property=\"og:image\"" ) then
92                 _,_,arturl = string.find( line, "content=\"(.-)\"" )
93             end
94             if string.match( line, " rel=\"author\"" ) then
95                 _,_,artist = string.find( line, "href=\"/user/([^\"]*)\"" )
96             end
97             -- JSON parameters, also formerly known as "swfConfig",
98             -- "SWF_ARGS", "swfArgs" ...
99             if string.match( line, "PLAYER_CONFIG" ) then
100                 if not fmt then
101                     prefres = get_prefres()
102                     if prefres >= 0 then
103                         fmt_list = string.match( line, "\"fmt_list\": \"(.-)\"" )
104                         if fmt_list then
105                             for itag,height in string.gmatch( fmt_list, "(%d+)\\/%d+x(%d+)\\/[^,]+" ) do
106                                 -- Apparently formats are listed in quality
107                                 -- order, so we take the first one that works,
108                                 -- or fallback to the lowest quality
109                                 fmt = itag
110                                 if tonumber(height) <= prefres then
111                                     break
112                                 end
113                             end
114                         end
115                     end
116                 end
117
118                 url_map = string.match( line, "\"url_encoded_fmt_stream_map\": \"(.-)\"" )
119                 if url_map then
120                     -- FIXME: do this properly
121                     url_map = string.gsub( url_map, "\\u0026", "&" )
122                     for url,itag in string.gmatch( url_map, "url=([^&,]+).-&itag=(%d+)" ) do
123                         -- Apparently formats are listed in quality order,
124                         -- so we can afford to simply take the first one
125                         if not fmt or tonumber( itag ) == tonumber( fmt ) then
126                             url = vlc.strings.decode_uri( url )
127                             path = url
128                             break
129                         end
130                     end
131                 end
132             -- There is also another version of the parameters, encoded
133             -- differently, as an HTML attribute of an <object> or <embed>
134             -- tag; but we don't need it now
135             end
136         end
137
138         if not path then
139             vlc.msg.err( "Couldn't extract youtube video URL, please check for updates to this script" )
140             return { }
141         end
142
143         if not arturl then
144             arturl = get_arturl()
145         end
146
147         return { { path = path; name = name; description = description; artist = artist; arturl = arturl } }
148     else -- This is the flash player's URL
149         video_id = get_url_param( vlc.path, "video_id" )
150         if not video_id then
151             _,_,video_id = string.find( vlc.path, "/v/([^?]*)" )
152         end
153         if not video_id then
154             vlc.msg.err( "Couldn't extract youtube video URL" )
155             return { }
156         end
157         fmt = get_url_param( vlc.path, "fmt" )
158         if fmt then
159             format = "&fmt=" .. fmt
160         else
161             format = ""
162         end
163         return { { path = "http://www.youtube.com/watch?v="..video_id..format } }
164     end
165 end