1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
|
--- a/share/lua/playlist/youtube.lua 2011-08-06 11:30:49.000000000 +0200
+++ b/share/lua/playlist/youtube.lua 2012-02-02 16:05:32.000000000 +0100
@@ -1,7 +1,7 @@
--[[
$Id$
- Copyright © 2007-2009 the VideoLAN team
+ Copyright © 2007-2011 the VideoLAN team
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
@@ -24,13 +24,27 @@
return res
end
-function get_arturl( path, video_id )
- if string.match( vlc.path, "iurl=" ) then
- return vlc.strings( get_url_param( vlc.path, "iurl" ) )
+function get_arturl()
+ local iurl = get_url_param( vlc.path, "iurl" )
+ if iurl then
+ return iurl
end
- if not arturl then
- return "http://img.youtube.com/vi/"..video_id.."/default.jpg"
+ local video_id = get_url_param( vlc.path, "v" )
+ if not video_id then
+ return nil
+ end
+ return "http://img.youtube.com/vi/"..video_id.."/default.jpg"
+end
+
+function get_prefres()
+ local prefres = -1
+ if vlc.var and vlc.var.inherit then
+ prefres = vlc.var.inherit(nil, "preferred-resolution")
+ if prefres == nil then
+ prefres = -1
+ end
end
+ return prefres
end
-- Probe function.
@@ -47,18 +61,17 @@
return false
end
end
- return ( string.match( vlc.path, "watch%?v=" ) -- the html page
- or string.match( vlc.path, "watch_fullscreen%?video_id=" ) -- the fullscreen page
- or string.match( vlc.path, "p.swf" ) -- the (old?) player url
- or string.match( vlc.path, "jp.swf" ) -- the (new?) player url (as of 24/08/2007)
- or string.match( vlc.path, "player2.swf" ) ) -- another player url
+ return ( string.match( vlc.path, "/watch%?" ) -- the html page
+ or string.match( vlc.path, "/v/" ) -- video in swf player
+ or string.match( vlc.path, "/player2.swf" ) ) -- another player url
end
-- Parse function.
function parse()
- if string.match( vlc.path, "watch%?v=" )
+ if string.match( vlc.path, "/watch%?" )
then -- This is the HTML page's URL
- -- fmt is the format of the video: 18 is HQ (mp4)
+ -- fmt is the format of the video
+ -- (cf. http://en.wikipedia.org/wiki/YouTube#Quality_and_codecs)
fmt = get_url_param( vlc.path, "fmt" )
while true do
-- Try to find the video's title
@@ -71,27 +84,42 @@
end
if string.match( line, "<meta name=\"description\"" ) then
-- Don't ask me why they double encode ...
- _,_,description = vlc.strings.resolve_xml_special_chars(vlc.strings.resolve_xml_special_chars(string.find( line, "content=\"(.-)\"" )))
+ _,_,description = string.find( line, "content=\"(.-)\"" )
+ description = vlc.strings.resolve_xml_special_chars( description )
+ description = vlc.strings.resolve_xml_special_chars( description )
end
- if string.match( line, "subscribe_to_user=" ) then
- _,_,artist = string.find( line, "subscribe_to_user=([^&]*)" )
+ if string.match( line, "<meta property=\"og:image\"" ) then
+ _,_,arturl = string.find( line, "content=\"(.-)\"" )
end
- -- CURRENT: var swfConfig = { [a lot of stuff...], "video_id": "OHVvVmUNBFc", "sk": "WswKuJzDBsdD6oG3IakCXgC", "t": "OEgsToPDskK3zO44y0QN8Fr5ZSAZwCQp", "plid": "AARGnwWMrmGkbpOxAAAA4AT4IAA"};
- -- OLD 1: var swfArgs = {hl:'en',BASE_YT_URL:'http://youtube.com/',video_id:'XPJ7d8dq0t8',l:'292',t:'OEgsToPDskLFdOYrrlDm3FQPoQBYaCP1',sk:'0gnr-AE6QZJEZmCMd3lq_AC'};
- -- OLD 2: var swfArgs = { "BASE_YT_URL": "http://youtube.com", "video_id": "OHVvVmUNBFc", "l": 88, "sk": "WswKuJzDBsdD6oG3IakCXgC", "t": "OEgsToPDskK3zO44y0QN8Fr5ZSAZwCQp", "plid": "AARGnwWMrmGkbpOxAAAA4AT4IAA", "tk": "mEL4E7PqHeaZp5OG19NQThHt9mXJU4PbRTOw6lz9osHi4Hixp7RE1w=="};
- -- OLD 3: 'SWF_ARGS': { [a lot of stuff...], "video_id": "OHVvVmUNBFc", "sk": "WswKuJzDBsdD6oG3IakCXgC", "t": "OEgsToPDskK3zO44y0QN8Fr5ZSAZwCQp", "plid": "AARGnwWMrmGkbpOxAAAA4AT4IAA"};
- if ( string.match( line, "PLAYER_CONFIG" ) or string.match( line, "swfConfig" ) or string.match( line, "SWF_ARGS" ) or string.match( line, "swfArgs" ) ) and string.match( line, "video_id" ) then
- if string.match( line, "BASE_YT_URL" ) then
- _,_,base_yt_url = string.find( line, "\"BASE_YT_URL\": \"(.-)\"" )
+ if string.match( line, " rel=\"author\"" ) then
+ _,_,artist = string.find( line, "href=\"/user/([^\"]*)\"" )
+ end
+ -- JSON parameters, also formerly known as "swfConfig",
+ -- "SWF_ARGS", "swfArgs", "PLAYER_CONFIG" ...
+ if string.match( line, "playerConfig" ) then
+ if not fmt then
+ prefres = get_prefres()
+ if prefres >= 0 then
+ fmt_list = string.match( line, "\"fmt_list\": \"(.-)\"" )
+ if fmt_list then
+ for itag,height in string.gmatch( fmt_list, "(%d+)\\/%d+x(%d+)\\/[^,]+" ) do
+ -- Apparently formats are listed in quality
+ -- order, so we take the first one that works,
+ -- or fallback to the lowest quality
+ fmt = itag
+ if tonumber(height) <= prefres then
+ break
+ end
+ end
+ end
+ end
end
- _,_,t = string.find( line, "\"t\": \"(.-)\"" )
- -- vlc.msg.err( t )
- -- video_id = string.gsub( line, ".*&video_id:'([^']*)'.*", "%1" )
- fmt_url_map = string.match( line, "\"url_encoded_fmt_stream_map\": \"(.-)\"" )
- if fmt_url_map then
+
+ url_map = string.match( line, "\"url_encoded_fmt_stream_map\": \"(.-)\"" )
+ if url_map then
-- FIXME: do this properly
- fmt_url_map = string.gsub( fmt_url_map, "\\u0026", "&" )
- for url,itag in string.gmatch( fmt_url_map, "url=([^&,]+).-&itag=(%d+)" ) do
+ url_map = string.gsub( url_map, "\\u0026", "&" )
+ for url,itag in string.gmatch( url_map, "url=([^&,]+)[^,]*&itag=(%d+)" ) do
-- Apparently formats are listed in quality order,
-- so we can afford to simply take the first one
if not fmt or tonumber( itag ) == tonumber( fmt ) then
@@ -101,75 +129,37 @@
end
end
end
- -- Also available on non-HTML5 pages: var swfHTML = (isIE) ? "<object [...]><param name=\"flashvars\" value=\"rv.2.thumbnailUrl=http%3A%2F%2Fi4.ytimg.com%2Fvi%2F3MLp7YNTznE%2Fdefault.jpg&rv.7.length_seconds=384 [...] &video_id=OHVvVmUNBFc [...] &t=OEgsToPDskK3zO44y0QN8Fr5ZSAZwCQp [...]
- elseif string.match( line, "swfHTML" ) and string.match( line, "video_id" ) then
- _,_,t = string.find( line, "&t=(.-)&" )
- -- Also available in HTML5 pages: videoPlayer.setAvailableFormat("http://v6.lscache4.c.youtube.com/videoplayback?ip=82.0.0.0&sparams=id%2Cexpire%2Cip%2Cipbits%2Citag%2Calgorithm%2Cburst%2Cfactor&algorithm=throttle-factor&itag=45&ipbits=8&burst=40&sver=3&expire=1275688800&key=yt1&signature=6ED860441298D1157FF3013A5D72727F25831F09.4C196BEA9F8F9B83CE678D79AD918B83D5E98B46&factor=1.25&id=7117715cf57d18d4", "video/webm; codecs="vp8.0, vorbis"", "hd720");
- elseif string.match( line, "videoPlayer%.setAvailableFormat" ) then
- url,itag = string.match( line, "videoPlayer%.setAvailableFormat%(\"(.-itag=(%d+).-)\",.+%)" )
- if url then
- -- For now, WebM formats are listed only in the HTML5
- -- section, that is also only when HTML5 is enabled.
- -- Format 45 is 720p, and 43 is lower resolution.
- if tonumber( itag ) == 45 or ( tonumber( itag ) == 43 and not webm_path ) then
- webm_path = url
- end
- -- Grab something if fmt_url_map failed
- if not path and ( not fmt or tonumber( itag ) == tonumber( fmt ) ) then
- path = url
- end
- end
+ -- There is also another version of the parameters, encoded
+ -- differently, as an HTML attribute of an <object> or <embed>
+ -- tag; but we don't need it now
end
end
- if not video_id then
- video_id = get_url_param( vlc.path, "v" )
+ if not path then
+ vlc.msg.err( "Couldn't extract youtube video URL, please check for updates to this script" )
+ return { }
end
- arturl = get_arturl( vlc.path, video_id )
- if not fmt then
- -- Prefer WebM formats if this is an &html5=True URL
- html5 = get_url_param( vlc.path, "html5" )
- if html5 == "True" and webm_path then
- path = webm_path
- end
+ if not arturl then
+ arturl = get_arturl()
end
- if not path then
- if not base_yt_url then
- base_yt_url = "http://youtube.com/"
- end
- if fmt then
- format = "&fmt=" .. fmt
- else
- format = ""
- end
-
- if t then
- path = base_yt_url .. "get_video?video_id="..video_id.."&t="..t..format
- else
- -- This shouldn't happen ... but keep it as a backup.
- path = "http://www.youtube.com/v/"..video_id
- end
- end
return { { path = path; name = name; description = description; artist = artist; arturl = arturl } }
else -- This is the flash player's URL
- if string.match( vlc.path, "title=" ) then
- name = vlc.strings.decode_uri(get_url_param( vlc.path, "title" ))
- end
video_id = get_url_param( vlc.path, "video_id" )
- arturl = get_arturl( vlc.path, video_id )
+ if not video_id then
+ _,_,video_id = string.find( vlc.path, "/v/([^?]*)" )
+ end
+ if not video_id then
+ vlc.msg.err( "Couldn't extract youtube video URL" )
+ return { }
+ end
fmt = get_url_param( vlc.path, "fmt" )
if fmt then
format = "&fmt=" .. fmt
else
format = ""
end
- if not string.match( vlc.path, "t=" ) then
- -- This sucks, we're missing "t" which is now mandatory. Let's
- -- try using another url
- return { { path = "http://www.youtube.com/v/"..video_id; name = name; arturl = arturl } }
- end
- return { { path = "http://www.youtube.com/get_video.php?video_id="..video_id.."&t="..get_url_param( vlc.path, "t" )..format; name = name; arturl = arturl } }
+ return { { path = "http://www.youtube.com/watch?v="..video_id..format } }
end
end
|