[vlc-commits] youtube.lua: use alternative API URL
Pierre Ynard
git at videolan.org
Mon Sep 17 06:05:14 CEST 2012
vlc | branch: master | Pierre Ynard <linkfanel at yahoo.fr> | Mon Sep 17 05:54:59 2012 +0200| [aaf17f6592d2cf8f122ed6d9291a8eadb4812576] | committer: Pierre Ynard
youtube.lua: use alternative API URL
It seems that the normal URLs included in the web page miss a
"signature" field and return 403 errors now. This approach has a number
of issues, it requires an extra HTTP request, still seems to fail due
to lack of signatures, and have different access restrictions than the
the web pages.
This shall meet the popular demand for now.
Closes #7471
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=aaf17f6592d2cf8f122ed6d9291a8eadb4812576
---
share/lua/playlist/youtube.lua | 126 ++++++++++++++++++++++++++++++++--------
1 file changed, 102 insertions(+), 24 deletions(-)
diff --git a/share/lua/playlist/youtube.lua b/share/lua/playlist/youtube.lua
index 20cb3a1..13018ba 100644
--- a/share/lua/playlist/youtube.lua
+++ b/share/lua/playlist/youtube.lua
@@ -1,7 +1,7 @@
--[[
$Id$
- Copyright © 2007-2011 the VideoLAN team
+ Copyright © 2007-2012 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
@@ -47,6 +47,50 @@ function get_prefres()
return prefres
end
+function get_fmt( fmt_list )
+ local prefres = get_prefres()
+ if prefres < 0 then
+ return nil
+ end
+
+ local fmt = nil
+ 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
+ return fmt
+end
+
+function pick_url( url_map, fmt )
+ local path = nil
+ -- Handle both orderings, as unfortunately both may appear
+ if string.match( url_map, "^url" ) then
+ 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
+ url = vlc.strings.decode_uri( url )
+ path = url
+ break
+ end
+ end
+ else
+ for itag,url in string.gmatch( url_map, "itag=(%d+)&[^,]*url=([^&,]+)" ) do
+ if not fmt or tonumber( itag ) == tonumber( fmt ) then
+ url = vlc.strings.decode_uri( url )
+ path = url
+ break
+ end
+ end
+ end
+ return path
+end
+
-- Probe function.
function probe()
if vlc.access ~= "http" and vlc.access ~= "https" then
@@ -62,6 +106,7 @@ function probe()
end
end
return ( string.match( vlc.path, "/watch%?" ) -- the html page
+ or string.match( vlc.path, "/get_video_info%?" ) -- info API
or string.match( vlc.path, "/v/" ) -- video in swf player
or string.match( vlc.path, "/player2.swf" ) ) -- another player url
end
@@ -73,6 +118,9 @@ function parse()
-- fmt is the format of the video
-- (cf. http://en.wikipedia.org/wiki/YouTube#Quality_and_codecs)
fmt = get_url_param( vlc.path, "fmt" )
+ -- URLs in the web page are no good since
+ -- they miss the "signature" parameter :/
+--[[
while true do
-- Try to find the video's title
line = vlc.readline()
@@ -98,20 +146,10 @@ function parse()
-- "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
+ fmt_list = string.match( line, "\"fmt_list\": \"(.-)\"" )
+ if fmt_list then
+ fmt_list = string.gsub( fmt_list, "\\/", "/" )
+ fmt = get_fmt( fmt_list )
end
end
@@ -119,21 +157,24 @@ function parse()
if url_map then
-- FIXME: do this properly
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
- url = vlc.strings.decode_uri( url )
- path = url
- break
- end
- end
+ path = pick_url( url_map, fmt )
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
+--]]
+
+ local video_id = get_url_param( vlc.path, "v" )
+ if video_id then
+ if fmt then
+ format = "&fmt=" .. fmt
+ else
+ format = ""
+ end
+ path = "http://www.youtube.com/get_video_info?video_id="..video_id..format.."&el=detailpage"
+ end
if not path then
vlc.msg.err( "Couldn't extract youtube video URL, please check for updates to this script" )
@@ -145,6 +186,43 @@ function parse()
end
return { { path = path; name = name; description = description; artist = artist; arturl = arturl } }
+
+ elseif string.match( vlc.path, "/get_video_info%?" ) then
+ local line = vlc.readline() -- data is on one line only
+
+ local fmt = get_url_param( vlc.path, "fmt" )
+ if not fmt then
+ local fmt_list = string.match( line, "&fmt_list=([^&]*)" )
+ if fmt_list then
+ fmt_list = vlc.strings.decode_uri( fmt_list )
+ fmt = get_fmt( fmt_list )
+ end
+ end
+
+ local url_map = string.match( line, "&url_encoded_fmt_stream_map=([^&]*)" )
+ if url_map then
+ url_map = vlc.strings.decode_uri( url_map )
+ path = pick_url( url_map, fmt )
+ end
+
+ if not path then
+ vlc.msg.err( "Couldn't extract youtube video URL, please check for updates to this script" )
+ return { }
+ end
+
+ local title = string.match( line, "&title=([^&]*)" )
+ if title then
+ title = string.gsub( title, "+", " " )
+ title = vlc.strings.decode_uri( title )
+ end
+ local artist = string.match( line, "&author=([^&]*)" )
+ local arturl = string.match( line, "&thumbnail_url=([^&]*)" )
+ if arturl then
+ arturl = vlc.strings.decode_uri( arturl )
+ end
+
+ return { { path = path, title = title, artist = artist, arturl = arturl } }
+
else -- This is the flash player's URL
video_id = get_url_param( vlc.path, "video_id" )
if not video_id then
More information about the vlc-commits
mailing list