Code: Select all
--[[
Parse YouTube playlists:
http://youtube.com/view_play_list?p=<playlist_ID>
http://gdata.youtube.com/feeds/api/playlists/<playlist_ID>
http://gdata.youtube.com/feeds/api/playlists/<playlist_ID>?v=2
--]]
function probe()
if vlc.access ~= "http" then
return false
end
return ( string.match( vlc.path, "youtube.com/view_play_list%?" )
or string.match( vlc.path, "gdata.youtube.com/feeds/api/playlists/" ) )
end
function parse()
-- if webpage URL, redirect to YouTube API v2 XML
-- the playlist webpage HTML layout may change over time but a specific version of the YouTube API shouldn't
if string.match( vlc.path, "view_play_list%?" ) then
playlist_ID = string.match( vlc.path, "[?&]p=([^&]+)" )
xml = {}
xml.path = "http://gdata.youtube.com/feeds/api/playlists/" .. playlist_ID .. "?v=2"
xml.path = xml.path .. "&max-results=1" -- prevents video URL expiration but now you can't easily browse videos out of order...
xml.name = "YouTube playlist"
return { xml }
end
-- parse feed XML and let existing YouTube Lua script handle individual videos
-- NOTE: this XML doesn't have line breaks after each tag. the only line breaks are from text content enclosed in tags
videos = {}
while true do
line = vlc.readline()
if not line then break end
for video_url in string.gmatch( line, "<media:player url='([^']+)'/>" ) do
table.insert( videos, { path = vlc.strings.resolve_xml_special_chars( video_url ) } )
end
-- check if there's a following XML file with more videos
if string.match( line, "<link rel='next' type='application/atom%+xml' href='([^']+)'/>" ) then
next_page = string.match( line, "<link rel='next' type='application/atom%+xml' href='([^']+)'/>" )
end
end
-- process next page of results after current items if there is one
if next_page then
table.insert( videos, { path = vlc.strings.resolve_xml_special_chars( next_page ); name = "more YouTube playlist videos..." } )
end
return videos
end
Quicklists? Hmm... I've never used those so I'm not familiar with them. Is there a public way to see someone's quicklist? I don't see them even mentioned in the YouTube API.WOW great job! Working pretty good for me. Just some feature requests for the next update:
1) Allow it to play the Youtube quicklist also
2) Can this playlist be saved? I had problems saving the playlist and reloading it
Code: Select all
--[[
Parse YouTube playlists:
http://youtube.com/view_play_list?p=<playlist_ID>
http://gdata.youtube.com/feeds/api/playlists/<playlist_ID>
http://gdata.youtube.com/feeds/api/playlists/<playlist_ID>?v=2
TODO: determine if it's feasible to allow easy video browsing through playlist
while preventing video URL expiration
TODO: add some ability to select different video qualities with &fmt=<quality>
--]]
function probe()
if vlc.access ~= "http" then
return false
end
return ( string.match( vlc.path, "youtube.com/view_play_list%?" )
or string.match( vlc.path, "gdata.youtube.com/feeds/api/playlists/" ) )
end
function parse()
-- if webpage URL, redirect to YouTube API v2 XML
-- the output from the YouTube API is easier to work with and should change less often than the webpage
if string.match( vlc.path, "view_play_list%?" ) then
playlist_ID = string.match( vlc.path, "[?&]p=([^&]+)" )
xml = {}
xml.name = "YouTube playlist"
xml.path = "http://gdata.youtube.com/feeds/api/playlists/" .. playlist_ID .. "?v=2"
-- paging through videos one at a time prevents video URL expiration but now you can't easily browse
-- videos out of order...
xml.path = xml.path .. "&max-results=1"
return { xml }
end
-- get current position in playlist
if string.match( vlc.path, "[?&]start%-index=([^&]+)" ) then
video_position = string.match( vlc.path, "[?&]start%-index=([^&]+)" )
else
video_position = 1
end
-- parse feed XML and let existing YouTube Lua script handle individual videos
-- NOTE: this XML doesn't have line breaks after each tag. the only line breaks are from text content
-- enclosed in tags
videos = {}
while true do
line = vlc.readline()
if not line then break end
-- get playlist name
if not playlist_name then -- first <title> tag is for playlist
if string.match( line, "<title>([^<]+)</title>" ) then
playlist_name = string.match( line, "<title>([^<]+)</title>" )
end
end
-- check if there's a following XML file with more videos
if string.match( line, "<link rel='next' type='application/atom%+xml' href='([^']+)'/>" ) then
next_page = string.match( line, "<link rel='next' type='application/atom%+xml' href='([^']+)'/>" )
next_page = vlc.strings.resolve_xml_special_chars( next_page ) -- fix the "&"s
end
-- get artist of playlist
if not playlist_artist then -- first <name> tag is for playlist
if string.match( line, "<name>([^<]+)</name>" ) then
playlist_artist = string.match( line, "<name>([^<]+)</name>" )
end
end
-- get video count in playlist
if string.match( line, "<openSearch:totalResults>(%d+)</openSearch:totalResults>" ) then
video_count = string.match( line, "<openSearch:totalResults>(%d+)</openSearch:totalResults>" )
video_count = tonumber( video_count )
end
-- get playlist description
if string.match( line, "<media:description [^>]*>([^<]+)</media:description>" ) then
playlist_desc = string.match( line, "<media:description [^>]*>([^<]+)</media:description>" )
end
-- get all videos from playlist
-- NOTE: although using the webpage URL defaults there to only being one video, you can still manually
-- enter a different YouTube API playlist feed URL which can have more than one
for video_url in string.gmatch( line, "<media:player url='([^']+)'/>" ) do
video_item = {}
video_item.path = vlc.strings.resolve_xml_special_chars( video_url )
video_item.name = playlist_name .. " (video " .. video_position .. ")"
video_item.artist = playlist_artist
table.insert( videos, video_item )
video_position = video_position + 1
end
end
-- process next page of results after current items if there is one
if next_page then
next_video_position = tonumber( string.match( next_page, "[?&]start%-index=(%d+)" ) )
next_xml = {}
next_xml.path = next_page
if next_video_position < video_count then
next_xml.name = playlist_name .. " (videos " .. next_video_position .. " to " .. video_count .. ")"
else
next_xml.name = playlist_name .. " (video " .. next_video_position .. ")"
end
next_xml.description = playlist_desc
next_xml.artist = playlist_artist
table.insert( videos, next_xml )
end
return videos
end
Code: Select all
function probe()
return vlc.access == "http" and string.match( vlc.path, "youtube.com/get_video%?" )
end
function parse()
if string.match( vlc.path, "[?&]video_id=([^&]+)" ) then
video_id = string.match( vlc.path, "[?&]video_id=([^&]+)" )
return "http://youtube.com/watch?v=" .. video_id
end
end
Code: Select all
--[[
Parse YouTube playlists:
http://youtube.com/view_play_list?p=<playlist_ID>
http://youtube.com/user/<user>#<mode>/(user|c)/<playlist_ID>
http://gdata.youtube.com/feeds/api/playlists/<playlist_ID>?v=2
TODO: determine if it's feasible to allow easy video browsing through playlist
while preventing video URL expiration
TODO: add some ability to select different video qualities with &fmt=<quality>
--]]
function probe()
if vlc.access ~= "http" then
return false
end
return ( string.match( vlc.path, "youtube.com/view_play_list%?" )
or string.match( vlc.path, "gdata.youtube.com/feeds/api/playlists/" )
or string.match( vlc.path, "youtube.com/user/[^/]+/[^/]+/%x+" ) )
end
function parse()
-- if webpage URL, redirect to YouTube API v2 XML
-- the output from the YouTube API is easier to work with and should change less often than the webpage
if string.match( vlc.path, "view_play_list%?" ) or string.match( vlc.path, "youtube.com/user" ) then
if string.match( vlc.path, "view_play_list%?" ) then
playlist_ID = string.match( vlc.path, "[?&]p=([^&]+)" )
else
playlist_ID = string.match( vlc.path, "youtube.com/user/[^/]+/[^/]+/(%x+)" )
end
xml = {}
xml.name = "YouTube playlist"
xml.path = "http://gdata.youtube.com/feeds/api/playlists/" .. playlist_ID .. "?v=2"
-- paging through videos one at a time prevents video URL expiration but now you can't easily browse
-- videos out of order...
xml.path = xml.path .. "&max-results=1"
return { xml }
end
-- get current position in playlist
if string.match( vlc.path, "[?&]start%-index=([^&]+)" ) then
video_position = string.match( vlc.path, "[?&]start%-index=([^&]+)" )
else
video_position = 1
end
-- parse feed XML and let existing YouTube Lua script handle individual videos
-- NOTE: this XML doesn't have line breaks after each tag. the only line breaks are from text content
-- enclosed in tags
videos = {}
while true do
line = vlc.readline()
if not line then break end
-- get playlist name
if not playlist_name then -- first <title> tag is for playlist
if string.match( line, "<title>([^<]+)</title>" ) then
playlist_name = string.match( line, "<title>([^<]+)</title>" )
end
end
-- check if there's a following XML file with more videos
if string.match( line, "<link rel='next' type='application/atom%+xml' href='([^']+)'/>" ) then
next_page = string.match( line, "<link rel='next' type='application/atom%+xml' href='([^']+)'/>" )
next_page = vlc.strings.resolve_xml_special_chars( next_page ) -- fix the "&"s
end
-- get artist of playlist
if not playlist_artist then -- first <name> tag is for playlist
if string.match( line, "<name>([^<]+)</name>" ) then
playlist_artist = string.match( line, "<name>([^<]+)</name>" )
end
end
-- get video count in playlist
if string.match( line, "<openSearch:totalResults>(%d+)</openSearch:totalResults>" ) then
video_count = string.match( line, "<openSearch:totalResults>(%d+)</openSearch:totalResults>" )
video_count = tonumber( video_count )
end
-- get playlist description
if string.match( line, "<media:description [^>]*>([^<]+)</media:description>" ) then
playlist_desc = string.match( line, "<media:description [^>]*>([^<]+)</media:description>" )
end
-- get all videos from playlist
-- NOTE: although using the webpage URL defaults there to only being one video, you can still manually
-- enter a different YouTube API playlist feed URL which can have more than one
for video_url in string.gmatch( line, "<media:player url='([^']+)'/>" ) do
video_item = {}
video_item.path = vlc.strings.resolve_xml_special_chars( video_url )
video_item.name = playlist_name .. " (video " .. video_position .. ")"
video_item.artist = playlist_artist
table.insert( videos, video_item )
video_position = video_position + 1
end
end
-- process next page of results after current items if there is one
if next_page then
next_video_position = tonumber( string.match( next_page, "[?&]start%-index=(%d+)" ) )
next_xml = {}
next_xml.path = next_page
if next_video_position < video_count then
next_xml.name = playlist_name .. " (videos " .. next_video_position .. " to " .. video_count .. ")"
else
next_xml.name = playlist_name .. " (video " .. next_video_position .. ")"
end
next_xml.description = playlist_desc
next_xml.artist = playlist_artist
table.insert( videos, next_xml )
end
return videos
end
Code: Select all
--[[
Parse YouTube playlists:
http://youtube.com/view_play_list?p=<playlist_ID>
http://youtube.com/user/<user>#<mode>/c/<playlist_ID>
http://gdata.youtube.com/feeds/api/playlists/<playlist_ID>
http://gdata.youtube.com/feeds/api/playlists/<playlist_ID>?v=2
TODO: determine if it's feasible to allow easy video browsing through playlist
while preventing video URL expiration
TODO: add some ability to select different video qualities with &fmt=<quality>
--]]
function probe()
if vlc.access ~= "http" then
return false
end
return ( string.match( vlc.path, "youtube.com/view_play_list%?" )
or string.match( vlc.path, "gdata.youtube.com/feeds/api/playlists/" )
or string.match( vlc.path, "youtube.com/user/[^/]+/c/[0-9A-F]+" )
)
end
function parse()
-- if webpage URL, redirect to YouTube API v2 XML
-- the output from the YouTube API is easier to work with and should change less often than the webpage
if string.match( vlc.path, "view_play_list%?" ) or string.match( vlc.path, "youtube.com/user" ) then
if string.match( vlc.path, "view_play_list%?" ) then
playlist_ID = string.match( vlc.path, "[?&]p=([^&]+)" )
else
playlist_ID = string.match( vlc.path, "youtube.com/user/[^/]+/c/([0-9A-F]+)" )
end
xml = {}
xml.name = "YouTube playlist"
xml.path = "http://gdata.youtube.com/feeds/api/playlists/" .. playlist_ID .. "?v=2"
-- paging through videos one at a time prevents video URL expiration but now you can't easily browse
-- videos out of order...
xml.path = xml.path .. "&max-results=1"
return { xml }
end
-- get current position in playlist
if string.match( vlc.path, "[?&]start%-index=([^&]+)" ) then
video_position = string.match( vlc.path, "[?&]start%-index=([^&]+)" )
else
video_position = 1
end
-- parse feed XML and let existing YouTube Lua script handle individual videos
-- NOTE: this XML doesn't have line breaks after each tag. the only line breaks are from text content
-- enclosed in tags
videos = {}
while true do
line = vlc.readline()
if not line then break end
-- get playlist name
if not playlist_name then -- first <title> tag is for playlist
if string.match( line, "<title>([^<]+)</title>" ) then
playlist_name = string.match( line, "<title>([^<]+)</title>" )
end
end
-- check if there's a following XML file with more videos
if string.match( line, "<link rel='next' type='application/atom%+xml' href='([^']+)'/>" ) then
next_page = string.match( line, "<link rel='next' type='application/atom%+xml' href='([^']+)'/>" )
next_page = vlc.strings.resolve_xml_special_chars( next_page ) -- fix the "&"s
end
-- get artist of playlist
if not playlist_artist then -- first <name> tag is for playlist
if string.match( line, "<name>([^<]+)</name>" ) then
playlist_artist = string.match( line, "<name>([^<]+)</name>" )
end
end
-- get video count in playlist
if string.match( line, "<openSearch:totalResults>(%d+)</openSearch:totalResults>" ) then
video_count = string.match( line, "<openSearch:totalResults>(%d+)</openSearch:totalResults>" )
video_count = tonumber( video_count )
end
-- get playlist description
if string.match( line, "<media:description [^>]*>([^<]+)</media:description>" ) then
playlist_desc = string.match( line, "<media:description [^>]*>([^<]+)</media:description>" )
end
-- get all videos from playlist
-- NOTE: although using the webpage URL defaults there to only being one video, you can still manually
-- enter a different YouTube API playlist feed URL which can have more than one
for video_url in string.gmatch( line, "<media:player url='([^']+)'/>" ) do
video_item = {}
video_item.path = vlc.strings.resolve_xml_special_chars( video_url )
video_item.name = playlist_name .. " (video " .. video_position .. ")"
video_item.artist = playlist_artist
table.insert( videos, video_item )
video_position = video_position + 1
end
end
-- process next page of results after current items if there is one
if next_page then
next_video_position = tonumber( string.match( next_page, "[?&]start%-index=(%d+)" ) )
next_xml = {}
next_xml.path = next_page
if next_video_position < video_count then
next_xml.name = playlist_name .. " (videos " .. next_video_position .. " to " .. video_count .. ")"
else
next_xml.name = playlist_name .. " (video " .. next_video_position .. ")"
end
next_xml.description = playlist_desc
next_xml.artist = playlist_artist
table.insert( videos, next_xml )
end
return videos
end
Huh? Your fix looks correct. Simply tweaking the regex to the new URL format YouTube changed to. It's always loaded one-by-one though. That's because it's just a simple wrapper around the existing "youtube.lua" script which takes a given video URL (e.g. youtube.com/watch?v=<video id>) and returns a video that VLC can play. All my script does is take a playlist and return a list of video URLs for youtube.lua to parse.Doesn't work anymore for new playlists on user profiles :(
e.g. http://www.youtube.com/user/<USERID>#p/c/<PLAYLISTID>
Tried fixing it. It loads the playlists but item by item, if I want to get to an item at the end of the playlist its very hindering.
Any idea how to fix that behaviour?
Code: Select all
http://gdata.youtube.com/feeds/api/playlists/foo?v=2&start-index=80
Code: Select all
xml.path = xml.path .. "&max-results=1"
Code: Select all
xml.path = xml.path .. "&max-results=50"
Return to “Scripting VLC in lua”
Users browsing this forum: No registered users and 26 guests