Name is required.
Email address is required.
Invalid email address
Answer is required.
Exceeding max length of 5KB

A 25 Videos limit in YouTube Playlist


Hi there,

Hmm... This looks bad... I installed JW on my website... Just for fun, a pure hobby project. OK, so I chose the JW player YouTube playlist option. So far so good. Everything looked nice. But now I noticed when I use the shuffle function it just shuffles between the first 25 entries of the playlist. Weird. I dunno if the reason is on the side of YT or if it is a limitation of the JW player.

Please help a brother.

Kind regards

POngy

44 Community Answers

Ethan Feldman

JW Player Support Agent  
0 rated :

Can you provide a link to where you are running this?

JW Player

User  
0 rated :

Sure Ethan, thanks for getting back.

URL: http://cli.gs/qE47pq

If you refresh the browser you'll start to notice a pattern - only the first 25 entries are being displayed.

Look, here's the original playlist:

http://www.youtube.com/view_play_list?p=552771756912D7CB

...It's got 64 entries but, well, I'm repeating myself but only the first 25 are ever shown on the website.

Ethan Feldman

JW Player Support Agent  
0 rated :

Cam you set the playlist flashvar to right or bottom so we can see physically how many items are listed?

JW Player

User  
0 rated :

It has been done and the result is 25 files!

JW Player

User  
0 rated :

8-o

JW Player

User  
0 rated :


See:*http://code.google.com/apis/youtube/2.0/developers_guide_protocol_api_query_parameters.html#max-resultssp*

25 is the default number of items that are returned when you request a playlist using the YouTube API.

Use max-results=nn to request up to 50 items.

JW Player

User  
0 rated :

Ah, so the max number is 50! The horror! I had so much fun developing my site and I was hoping to add lots and lots of videos, y'know being an amateur video picking editor, just displaying comedies and sweet pop music!

JW Player

User  
0 rated :

Please tell me there's a way around this!

JW Player

User  
0 rated :

I wouldn't think so POngy, I tried doing 51 and got blocked.

http://gdata.youtube.com/feeds/api/videos?vq=E3&start-index=1&max-results=51

Ethan Feldman

JW Player Support Agent  
0 rated :

@POngy – Yeah, you might have to make multiple players for something like this.

JW Player

User  
0 rated :

Hmm... OK, I've started thinking about ways around this. Perhaps if the JW API allows me to forward the viewer to another page after having watched Y numbers of videos. Sounds like a long shot but I have to start somewhere.

JW Player

User  
0 rated :


You can use various methods, such as dropdown forms or buttons, links, images, etc., to allow the user to load a new playlist.

See:*http://willswonders.myip.org:8074/player5/Simple_YouTube_Channel_v5.html*

For the second, third, etc., playlists, use:
bc.. http://gdata.youtube.com/feeds/api/videos?vq=E3&start-index=51&max-results=50
http://gdata.youtube.com/feeds/api/videos?vq=E3&start-index=101&max-results=50



*_Note that the YouTube API recommends that you only request 10 items._*
bc.. However, for displaying lists of videos, we recommend that you set the max-results parameter to 10.

JW Player

User  
0 rated :

But I'm very fond of the format autoplay + shuffle. I'd like to allow the viewer to just sit back and relax, not having to click a lot of button and make choices. One site, a video player, clean and simple.

So I'd need to integrate that concept into a working script, taking into consideration the 50 videos limit somehow.

JW Player

User  
0 rated :

buttons

JW Player

User  
0 rated :


So use a simple serverside PHP script to request 10,000 playlists of 50 items each, concatenate them into one *gigantic* playlist and load it into the JW Player. Should keep your users entertained forever!

This should get you started:
bc.. <?php

// YouTube_Playlist_XSPF-3.1.php 20071218
// playlists need to be updated at least every 2 hours
// call with: http://willswonders.myip.org:8085/php/YouTube_Playlist_XSPF-3.1.php?playlistid=B8D6FA74D3F2629C
// call with: http://my.site.org/YouTube_Playlist_XSPF-3.1.php?playlistid=9A337BB0628CF018

$debug_output = true;
$update_interval = 2;
$cachedirectory = '/Program Files/Apache Group/Apache2/Will\'s Wonders/php/cache/';


// debug('Playlist ID', $_GET['playlistid']);


// for command line argument passing
if (isset($_SERVER['argv'][1]))
{
$_GET['playlistid'] = $_SERVER['argv'][1];
}


// debug('Playlist ID', $_GET['playlistid']); exit;


// my playlist
$playlistid = (isset($_GET["playlistid"])) ? strval($_GET["playlistid"]) : "B8D6FA74D3F2629C";
// johnyradio 9A337BB0628CF018
// $playlistid = (isset($_GET["playlistid"])) ? strval($_GET["playlistid"]) : "9A337BB0628CF018";
// ToothandNail 4F7A36C13B0C5764
// $playlistid = (isset($_GET["playlistid"])) ? strval($_GET["playlistid"]) : "4F7A36C13B0C5764";
// UMG 5C06802F841BE277
// $playlistid = (isset($_GET["playlistid"])) ? strval($_GET["playlistid"]) : "5C06802F841BE277";
// WatchMojo 2C9178C3EFE262EF
// $playlistid = (isset($_GET["playlistid"])) ? strval($_GET["playlistid"]) : "2C9178C3EFE262EF";
// National Geographic - top videos
// $playlistid = (isset($_GET["playlistid"])) ? strval($_GET["playlistid"]) : "B4EF96652BFE5853";

// max-results is limited to 50 per request, total of 100 for playlists
// http://gdata.youtube.com/feeds/api/playlists/45C563323B344971 ?start-index=1&max-results=50
$playlisturl1 = "http://gdata.youtube.com/feeds/api/playlists/" . $playlistid . "?start-index=1&max-results=50";
$playlisturl2 = "http://gdata.youtube.com/feeds/api/playlists/" . $playlistid . "?start-index=51&max-results=50";

// create cache filename
$patterns = array('#gdata#', '#/#', '#:#', '#\.#', '#http#', '#youtube#', '#com#', '#feeds#', '#api#', '#playlists#', '#\?start-index=1&max-results=50#');
$replacements = array( '', '', '', '', '', '', '', '', '', 'playlists_', '');
$filename = preg_replace($patterns, $replacements, $playlisturl1);


// debug(' Playlist ID', $playlistid);
// debug(' Playlist URL', $playlisturl);
// debug('Cache Filename', $cachefilename);
// exit;


for ($i=0; $i < $update_interval; $i++)
{
$cachefilename = (date('YmdH') - $i) . '_' . $filename . ".xml";
if (file_exists($cachedirectory . $cachefilename))
{
if (!isset($_SERVER['argv'][1]))
{
header ("content-type: text/xml");
print file_get_contents($cachedirectory . $cachefilename);
}
exit;
}
}

$cachefilename = date('YmdH') . '_' . $filename . ".xml";

$playlistcontent1 = file($playlisturl1);
$playlistcontent2 = file($playlisturl2);
$playlistcontent = array_merge($playlistcontent1, $playlistcontent2);

$contentstring = "";
foreach($playlistcontent as $value)
{
$contentstring .= rtrim($value);
}

$contentarray = explode("<entry>", $contentstring);


// debug('Playlist Content', $playlistcontent);
// debug('Content String', $contentstring);
// debug('Content Array', $contentarray);
// exit;


$track = 0;
$type = '';

// construct XSPF playlist headers
$playlist = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
$playlist .= "<playlist version=\"1\" xmlns=\"http://xspf.org/ns/0/\">\n";
$playlist .= " <trackList>\n";

// construct XSPF playlist tracks
while($junk = next($contentarray))
{
$track++;
$playlist .= " <track>\n";

if ((preg_match('/<title>(.*?)<\/title>/', $junk, $match)) || (preg_match('/<title type=\'text\'>(.*?)<\/title>/', $junk, $match)))
{
$playlist .= " <title>" . $match[1] . "</title>\n";
}
if (preg_match('/<name>(.*?)<\/name>/', $junk, $match))
{
$playlist .= " <author>" . $match[1] . "</author>\n";
if ($match[1] == 'universalmusicgroup')
{
$type = 'UMG';
}
}
// <media:thumbnail url='http://img.youtube.com/vi/izoZ-hjbKJQ/0.jpg
if (preg_match('/<media:thumbnail url=.*?<media:thumbnail url=.*?<media:thumbnail url=.*?<media:thumbnail url=\'(.*?)0.jpg/', $junk, $match))
{
$playlist .= " <image>" . $match[1] . "0.jpg</image>\n";
}
// <media:content url=\'http:\/\/www.youtube.com\/v\/ds6oTHYmqRc\' type
if (preg_match('/<media:content url=\'http:\/\/www.youtube.com\/v\/(.*?)\' type/', $junk, $match))
{
$videoid = $match[1];
// http://youtube.com/v/ds6oTHYmqRc.swf
$page = @file_get_contents('http://youtube.com/v/' . $videoid . '.swf');
if ((preg_match('/&t=(.*?)&/', $http_response_header[5], $match)) || (preg_match('/&t=(.*)/', $http_response_header[5], $match)))
{
$playlist .= " <location>http://www.youtube.com/get_video.php?video_id=" . $videoid . "&t=" . $match[1] . "</location>\n";
}
}
else if (preg_match('/<media:player url=\'http:\/\/www.youtube.com\/watch\?v=(.*?)\'/', $junk, $match))
{
$videoid = $match[1];
$page = @file_get_contents('http://youtube.com/watch?v=' . $videoid);
// check html in $page for: var swfArgs = {video_id:'lNvWoi0TesY',l:'217',t:'OEgsToPDskKER2zcpXlSd7ZzYDMp35hB',sk:'ASVXJ-JA-T6kbJT7maMDnwC',sw:'0.05',tk:'SZEt22MOl18ADaQJ-c9onimRL-HKw9HxGyYbBkoyguEPPDq_ttbaow=='};
preg_match('/t:\'(.*?)\'/', $page, $match);
// http://www.youtube.com/get_video.php?video_id= lNvWoi0TesY & t=OEgsToPDskKER2zcpXlSd7ZzYDMp35hB
$playlist .= " <location>http://www.youtube.com/get_video.php?video_id=" . $videoid . "&t=" . $match[1] . "</location>\n";


// debug( 'Page', $page);
// debug( 'Match[1]', $match[1]);
// exit;


}
$playlist .= " <meta rel=\"type\">flv</meta>\n";
$playlist .= " <annotation>Track " . $track . "</annotation>\n";
$playlist .= " </track>\n";

if (($track > 19) && ($type == 'UMG'))
{
break;
}
}

// construct XSPF playlist footers
$playlist .= " </trackList>\n";
$playlist .= "</playlist>\n";

if (!isset($_SERVER['argv'][1]))
{
header ("content-type: text/xml");
print $playlist;
}

// check cache - write to cache
if (!file_exists($cachedirectory . $cachefilename))
{
$fh = fopen($cachedirectory . $cachefilename, 'a');

fwrite($fh, $playlist);

fclose($fh);
}

// cleanup cache
@$directory_handle = dir($cachedirectory);

if ($directory_handle)
{
while (false !== ($currentfile = $directory_handle->read()))
{
// 200712050018_playlists_9A337BB0628CF018.xml
if (preg_match('/(\d{10})_playlists_.*?.xml/', $currentfile, $match))
{
$currentdate = date('YmdH');


// debug('Current Date', $currentdate);
// debug('Current File', $currentfile);
// debug(' Match[1]', $match[1]);


// if file is older than current hour - update interval, delete file
if ($match[1] < $currentdate - $update_interval + 1)
{
unlink($cachedirectory . $currentfile);
}
}
}
$directory_handle->close();
}


function debug($title, $value)
{
global $debug_output;

if ($debug_output)
{
print "<pre>";
if (is_array($value))
{
print $title . ":\n";
print_r($value);
}
else
{
print $title . ": " . $value;
}
print "</pre>\n";
}
}

?>



*_Note that this is from 2007, so the YouTube API may have changed slightly._*

JW Player

User  
0 rated :

Alright, let's put that script into practice. Creating a huge playlist from many shorter ones was pretty much what I had in mind - the tricky part is turning the idea into a practical application. Here we go, it's gonna be a long ride...

URL: http://cli.gs/bPEuNr

Result: Parse error: syntax error, unexpected '}' in /home/a7426907/public_html/oevideo.php on line 120

JW Player

User  
0 rated :

Aw... No one is helping...

JW Player

User  
0 rated :


Updated PHP script Test Page:

*http://willswonders.myip.org:8074/player5/YouTube_Playlist_XSPF-3.1.php?playlistid=B8D6FA74D3F2629C*

Updated PHP script:
bc.. <?php

// YouTube_Playlist_XSPF-3.1.php 20100713
// playlists need to be updated at least every 2 hours
// call with: http://willswonders.myip.org:8074/player5/YouTube_Playlist_XSPF-3.1.php?playlistid=B8D6FA74D3F2629C
// call with: http://my.site.org/YouTube_Playlist_XSPF-3.1.php?playlistid=9A337BB0628CF018

$update_interval = 2;
$cachedirectory = '/nginx/html/cache/';

// for command line argument passing
if (isset($_SERVER['argv'][1]))
{
$_GET['playlistid'] = $_SERVER['argv'][1];
}


// debug('Playlist ID', $_GET['playlistid']);
// exit;


// my playlist
$playlistid = (isset($_GET["playlistid"])) ? strval($_GET["playlistid"]) : "B8D6FA74D3F2629C";
// johnyradio 9A337BB0628CF018
// $playlistid = (isset($_GET["playlistid"])) ? strval($_GET["playlistid"]) : "9A337BB0628CF018";
// ToothandNail 4F7A36C13B0C5764
// $playlistid = (isset($_GET["playlistid"])) ? strval($_GET["playlistid"]) : "4F7A36C13B0C5764";
// UMG 5C06802F841BE277
// $playlistid = (isset($_GET["playlistid"])) ? strval($_GET["playlistid"]) : "5C06802F841BE277";
// WatchMojo 2C9178C3EFE262EF
// $playlistid = (isset($_GET["playlistid"])) ? strval($_GET["playlistid"]) : "2C9178C3EFE262EF";
// National Geographic - top videos
// $playlistid = (isset($_GET["playlistid"])) ? strval($_GET["playlistid"]) : "B4EF96652BFE5853";

// max-results is limited to 50 per request, total of 100 for playlists
// http://gdata.youtube.com/feeds/api/playlists/45C563323B344971 ?start-index=1&max-results=50
$playlisturl1 = "http://gdata.youtube.com/feeds/api/playlists/" . $playlistid . "?start-index=1&max-results=50";
$playlisturl2 = "http://gdata.youtube.com/feeds/api/playlists/" . $playlistid . "?start-index=51&max-results=50";

// create cache filename
$patterns = array('#gdata#', '#/#', '#:#', '#\.#', '#http#', '#youtube#', '#com#', '#feeds#', '#api#', '#playlists#', '#\?start-index=1&max-results=50#');
$replacements = array( '', '', '', '', '', '', '', '', '', 'playlists_', '');
$filename = preg_replace($patterns, $replacements, $playlisturl1);


// debug(' Playlist ID', $playlistid);
// debug(' Playlist URL 1', $playlisturl1);
// debug(' Playlist URL 2', $playlisturl2);
// exit;


for ($i=0; $i < $update_interval; $i++)
{
$cachefilename = (date('YmdH') - $i) . '_' . $filename . ".xml";
if (file_exists($cachedirectory . $cachefilename))
{
if (!isset($_SERVER['argv'][1]))
{
header ("content-type: text/xml");
print file_get_contents($cachedirectory . $cachefilename);
}
exit;
}
}

$cachefilename = date('YmdH') . '_' . $filename . ".xml";


// debug('Cache Filename', $cachefilename);
// exit;


$playlistcontent1 = file($playlisturl1);
$playlistcontent2 = file($playlisturl2);
$playlistcontent = array_merge($playlistcontent1, $playlistcontent2);

$contentstring = "";

foreach($playlistcontent as $value)
{
$contentstring .= rtrim($value);
}

$contentarray = explode("<entry>", $contentstring);


// debug('Playlist Content', $playlistcontent);
// debug('Content String', $contentstring);
// debug('Content Array', $contentarray);
// exit;


$track = 0;
$type = '';

// construct XSPF playlist headers
$playlist = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
$playlist .= "<playlist version=\"1\" xmlns=\"http://xspf.org/ns/0/\">\n";
$playlist .= " <trackList>\n";

// construct XSPF playlist tracks
while($junk = next($contentarray))
{
$track++;
$playlist .= " <track>\n";

if ((preg_match('/<title>(.*?)<\/title>/', $junk, $match)) || (preg_match('/<title type=\'text\'>(.*?)<\/title>/', $junk, $match)))
{
$playlist .= " <title>" . $match[1] . "</title>\n";


// debug('Playlist', $playlist);
// debug('Match[1]', $match[1]);
// exit;


}

if (preg_match('/<name>(.*?)<\/name>/', $junk, $match))
{
$playlist .= " <author>" . $match[1] . "</author>\n";


// debug('Playlist', $playlist);
// debug('Match[1]', $match[1]);
// exit;


}

// <media:thumbnail url='http://img.youtube.com/vi/izoZ-hjbKJQ/0.jpg
if (preg_match('/<media:thumbnail url=.*?<media:thumbnail url=.*?<media:thumbnail url=.*?<media:thumbnail url=\'(.*?)0.jpg/', $junk, $match))
{
$playlist .= " <image>" . $match[1] . "0.jpg</image>\n";


// debug('Playlist', $playlist);
// debug('Match[1]', $match[1]);
// exit;


}


//...dubugging
// preg_match('/<media:content url=\'(.*?)\?f=playlists/', $junk, $match);
// print $junk;
// print_r($match);


// <media:content url='http://www.youtube.com/v/5GE82tqcYYQ?f=playlists&app=youtube_gdata' type='application/x-shockwave-flash' medium='video' isDefault='true' expression='full' duration='723' yt:format='5'/>
// <media:content url=\'(.*?)\?f=playlists&app=youtube_gdata' type='application/x-shockwave-flash' medium='video' isDefault='true' expression='full' duration='723' yt:format='5'/>
if (preg_match('/<media:content url=\'(.*?)\?f=playlists/', $junk, $match))
{
$playlist .= " <location>" . $match[1] . "</location>\n";


// debug('Playlist', $playlist);
// debug('Match[1]', $match[1]);


}

$playlist .= " <meta rel=\"type\">youtube</meta>\n";
$playlist .= " <annotation>Track " . $track . "</annotation>\n";
$playlist .= " </track>\n";


// debug('Playlist', $playlist);
// if($track > 4) break;


}

// construct XSPF playlist footers
$playlist .= " </trackList>\n";
$playlist .= "</playlist>\n";


if (!isset($_SERVER['argv'][1]))
{
header ("content-type: text/xml");
print $playlist;
}

// check cache - write to cache
if (!file_exists($cachedirectory . $cachefilename))
{
$fh = fopen($cachedirectory . $cachefilename, 'a');

fwrite($fh, $playlist);

fclose($fh);
}

// cleanup cache
@$directory_handle = dir($cachedirectory);

if ($directory_handle)
{
while (false !== ($currentfile = $directory_handle->read()))
{
// 200712050018_playlists_9A337BB0628CF018.xml
if (preg_match('/(\d{10})_playlists_.*?.xml/', $currentfile, $match))
{
$currentdate = date('YmdH');


// debug('Current Date', $currentdate);
// debug('Current File', $currentfile);
// debug(' Match[1]', $match[1]);


// if file is older than current hour - update interval, delete file
if ($match[1] < $currentdate - $update_interval + 1)
{
unlink($cachedirectory . $currentfile);
}
}
}
$directory_handle->close();
}


function debug($title, $value)
{
global $debug_output;

print "<pre>";
if (is_array($value))
{
print $title . ":\n";
print_r($value);
}
else
{
print $title . ": " . $value;
}
print "</pre>\n";
}

?>




Makes a gigantasaurus playlist like this:
bc.. <playlist version="1" xmlns="http://xspf.org/ns/0/">
<trackList>
<track>
<title>Best Feeling Ever... omg</title>
<author>kicesie</author>
<image>http://i.ytimg.com/vi/5GE82tqcYYQ/0.jpg</image>
<location>http://www.youtube.com/v/5GE82tqcYYQ</location>
<meta rel="type">youtube</meta>
<annotation>Track 1</annotation>
</track>
<track>
<title>2 Hot Girls in the Shower #8 - Bar Mitzvah Money</title>
<author>LKGProductions</author>
<image>http://i.ytimg.com/vi/P_1z7BbVNiY/0.jpg</image>
<location>http://www.youtube.com/v/P_1z7BbVNiY</location>
<meta rel="type">youtube</meta>
<annotation>Track 2</annotation>
</track>



<track>
<title>Christmas Village de Nol 2007 - de jour</title>
<author>jeroden2000</author>
<image>http://i.ytimg.com/vi/ost8y6PTCaM/0.jpg</image>
<location>http://www.youtube.com/v/ost8y6PTCaM</location>
<meta rel="type">youtube</meta>
<annotation>Track 65</annotation>
</track>
<track>
<title>Casting Modelo Krisztina Stein de Contempo Models</title>
<author>contempomodels</author>
<image>http://i.ytimg.com/vi/JNGFtn0L3LQ/0.jpg</image>
<location>http://www.youtube.com/v/JNGFtn0L3LQ</location>
<meta rel="type">youtube</meta>
<annotation>Track 66</annotation>
</track>
</trackList>
</playlist>



JW Player

User  
0 rated :

...I'm trying to understand it all at the moment, I'll let you know when I've analyzed and tested everything, could take a little while.

JW Player

User  
0 rated :

Ok, I get the following error when I try to run the script on my site:

Parse error: syntax error, unexpected '&' in /home/a7426907/public_html/createplaylist.php on line 145

Line 145 is the one that says:

if (preg_match('/<media:content url=\'(.*?)\?f=playlists/', $junk, $match))
{
$playlist .= " <location>" . $match[1] . "</location>\n";

I'm all into this idea, you seem to understand what I'm trying to do. Sorry if I fumble a bit when it comes to PHP but I will sort this out. But to do that I'll need your help.

I mean I can put the script on my site and if I've understood you correctly I will then be able to just put the URL in the JW playlist and the result will be fine. I mean I've already tried it (see http://cli.gs/qE47pq) so I know it works. What remains is being able to run the script on my site and replacing the playlist ID's with the ones I want to use, I reckon.

Feedback please. And if there's anything I can do for you in return just let me know.

JW Player

User  
0 rated :

Unfortunately, this forum software adds the HTML entity "& #10;" in random places.

Download this script and change the filename extension from "txt" to "php".

*http://willswonders.myip.org:8074/player5/YouTube_Playlist_XSPF-3.1.txt*

JW Player

User  
0 rated :

Craterscore,

Ok, I've downloaded the script, changed the extension and uploaded it to my site:

URL: aoioe.tk/YouTube_Playlist_XSPF-3.1.php

When I try to check it in Firefox I get the following error:

XML Parsing Error: junk after document element
Location: http://aoioe.tk/YouTube_Playlist_XSPF-3.1.php
Line Number 524, Column 1:

But when I check what should be the same script on your site (http://willswonders.myip.org:8074/player5/YouTube_Playlist_XSPF-3.1.php) I get a nice and clean XML file, so I guess the same little issue remains - the script seems to work but only when I call it from your website; please help me check the error so I can call it from my own site.

JW Player

User  
0 rated :

You're getting some warnings and errors because you don't have a cache directory.
bc.. </track>
</trackList>
</playlist>
<br><table border='1' cellpadding='2' bgcolor='#FFFFDF' bordercolor='#E8B900' align='center'><tr><td><font face='Arial' size='1' color='#000000'>*PHP Error Message*</font></td></tr></table><br />
*Warning*: *fopen(/nginx/html/cache/2010072011_playlists_B8D6FA74D3F2629C.xml)* [<a href='function.fopen'>function.fopen</a>]: failed to open stream: No such file or directory in */home/a7426907/public_html/YouTube_Playlist_XSPF-3.1.php* on line *189*<br />
<br><table border='1' cellpadding='2' bgcolor='#FFFFDF' bordercolor='#E8B900' align='center'><tr><td><div align='center'><a href='http://www.000webhost.com/'><font face='Arial' size='1' color='#000000'>Free Web Hosting</font></a></div></td></tr></table><br><table border='1' cellpadding='2' bgcolor='#FFFFDF' bordercolor='#E8B900' align='center'><tr><td><font face='Arial' size='1' color='#000000'>*PHP Error Message*</font></td></tr></table><br />
*Warning*: fwrite(): supplied argument is not a valid stream resource in */home/a7426907/public_html/YouTube_Playlist_XSPF-3.1.php* on line *191*<br />
<br><table border='1' cellpadding='2' bgcolor='#FFFFDF' bordercolor='#E8B900' align='center'><tr><td><div align='center'><a href='http://www.000webhost.com/'><font face='Arial' size='1' color='#000000'>Free Web Hosting</font></a></div></td></tr></table><br><table border='1' cellpadding='2' bgcolor='#FFFFDF' bordercolor='#E8B900' align='center'><tr><td><font face='Arial' size='1' color='#000000'>*PHP Error Message*</font></td></tr></table><br />
*Warning*: fclose(): supplied argument is not a valid stream resource in */home/a7426907/public_html/YouTube_Playlist_XSPF-3.1.php* on line *193*



So make a directory named "cache" off of the root of your site.

Also, your web host is adding some analytics code at the end of the output. You may need to find out how to turn that off when it's a PHP script, so the playlist file is clean.
bc.. <br />
<br><table border='1' cellpadding='2' bgcolor='#FFFFDF' bordercolor='#E8B900' align='center'><tr><td><div align='center'><a href='http://www.000webhost.com/'><font face='Arial' size='1' color='#000000'>Free Web Hosting</font></a></div></td></tr></table>

<!-- www.000webhost.com Analytics Code -->
<script type="text/javascript" src="http://analytics.hosting24.com/count.php"></script>
<noscript><a href="http://www.hosting24.com/"><img src="http://analytics.hosting24.com/count.php" alt="web hosting" /></a></noscript>
<!-- End Of Analytics Code -->


JW Player

User  
0 rated :

Craterscore,

I will try to fix this ASAP and I will let you know the outcome.

JW Player

User  
0 rated :

Craterscore,

I've disabled the analytics code for the site in accordance with the host's instructions - well it should be turned off now unless there are some additional requirements from their side - I will follow up on that if I have to but I get another error message now when I try to run the script:

XML Parsing Error: XML or text declaration not at start of entity
Location: http://aoioe.tk/YouTube_Playlist_XSPF-3.1.php
Line Number 8, Column 254:

Oh, and I added a folder called cache to the public_html folder too - that's as high up in the root structure as I'm allowed to upload files and folders to.

Implementing, implementing, doing my best here - well, almost at least, there's a bunch of other stuff I'm trying to do if not simultaneously then at least during the course of the day, so at best I manage to squeeze in an hour or two of programming and/or creative work in the afternoons.

Cheers,

JW Player

User  
0 rated :


You are still getting the warning from not having a "cache" directory and there is still a message from your webhost at the end of the playlist.

Load your playlist in your browser*http://aoioe.tk/YouTube_Playlist_XSPF-3.1.php*

Then View, Source.

JW Player

User  
0 rated :

Ah, yes, I did check the source last time - at first I got another error message - I don't know why but anyways - I'm working on having the analytics code removed right now - it's not as easy as it should be but I think I'll get there eventually; I did create a folder named "cache" in the public_html folder because I supposed that was erm... what I was supposed to do... I'll be back.

JW Player

User  
0 rated :

Hi Craterscore,

These additional junk text snippets are a bit bothersome so I will circumvent that issue at the moment, possibly to solve it later or find a new web hotel - meanwhile I put the script on my old commercial web hotel, so the script is now located at:

URL: http://oakleaf.web.surftown.se/oe/YouTube_Playlist_XSPF-3.1.php

...If you look at it you'll notice that it produces a nice clean script just as expected; so with that taken care of at least temporarily the main page should work:

URL: http://aoioe.tk

...Unfortunately it does not - I followed your suggestion in the PHP commentary (// call with: http://my.site.org/YouTube_Playlist_XSPF-3.1.php?playlistid=9A337BB0628CF018), which should translate to http://oakleaf.web.surftown.se/oe/YouTube_Playlist_XSPF-3.1.php?playlistid=9A337BB0628CF018 but well erm... yeah, I guess I'll keep on working on it till it works - with your help of course, otherwise I would not be able to sort this out. So I hope I've been clear with the current situation - the PHP script seems to work but I can't call it from the site.

Kind regards

Pongy

JW Player

User  
0 rated :

Aw...

JW Player

User  
0 rated :

@ Pongy
@ Craterscore

I have been looking at this problem for 2 years
i'm not a programmer..but have 6000 hours of intense youtube-experience.

The approach to generate XMl playlists from Gdata-playlists is wrong
well not really wrong but not good enough.

Because of this:

1)

Gdata(playlists and the playlist-system is still full of bugs (@Youtube)

2)

Gdata still can not discriminate good enough between available and non-available videos
there's tens of reasons why videos are not available (removed,restricted,non-embedable...etc)
As a result you may get a playlist from Gdata which is simply incorrect since it may contain
videos that will not play in your player...which may cause your player to "hang"
To avoid this you will have to manually remove unavailable videos...which is unworkable if you
have many videos in many playlists ( i got 1000's in a 100 playlists)

3)

You dont neccesarely want to play only your own videos that you have uploaded yourself
you may (most certainly) also want to play from YOUR playlists that contain videos from other
youtube-users.
Now what happens if your channel gets suspended...which happens a lot for many (fair and unfair)
reasons...Right your playlist will be gone also...so you cant use Gdata anymore to make a list
of videos in that list..even if the videos in that list are not from your own youtube-account.


What is needed is a XML-file (or other format) which you populate manually with youtube-iD's
(or full Youtube video-urls's)...best if the urls to the titles and thumbnails dont need to be included (to much work) and are genreated (requested) by the player itself(just like it does
when you use the Gdata playlist format)

Yes a additional tool to grab the individual id's (or url's) might be handy to start
if you have long playlist at youtube that need to be converted to a list of individual
id's/urls i have such a tool (made for me) which is based on Microsoft Office (runtime)..you enter a username and it outputs a(configurable) XML-file with all that users playlists ....with in each separate playlist all the individual video-url's.

Now my question (also separately posted in the forum):


---////---------

Youtube-Playlist from XML (containig a list of individual Youtube-id's/URL's)

Can you refer me to the full instructions (on a relative beginners level)
how to make the JW-player play Youtube videos from a XML-file (or similar)that contains
(only) a list of individual Youtube-video-iD's (URL's) ?

I dont want to use the Gdata playlist format...because:

1) Does have to many bugs (@youtube) takes years before they solve them.
2) Gdata-Playlist disappear from Youtube for many reasons...individual id's not.
3) Restricted to 50 ...need more in one playlist.

Would be nice if i can get examples of how to use it with your (JW) wizard.
or otherwise a full example of Embed-code + XMl for a short playlist.
If a crossdomain-file is needed...please include that also.

Not shure which version (4 or 5) to use...but eventually (or better now)
i will need to play in Youtube-HD.

Best if it can be used without (to much) modification later when the Youtube-HD
option becomes available (if ever ;-)

I have been reading the fora...etc for over 2 years...dont find a answer or
understandable instructions for a non-programmer with just some general knowledge.

Thanks !

---///-------



I asked that question also here:

http://www.longtailvideo.com/support/forums/jw-player/using-playlists/13245/youtube-playlist-from-xml-containing-a-list-of-individual-you

After having read this thread i need to add that i want to use a XML (or other format)
where i dont need to add also the urls to the youtube-thumbnails and also the url to the title
this should not be needed...since the player dont need that incase of a gdata-playlist either
On top of that i have seen (other)players that only need the url to the video (video-iD) and these wil generate the titles,description amd thumbnails using some internal magic.

Youtube-HD is another issue ...best if any answers to my questions take into account
that it best also should work with a possible still to be expected Youtube-HD feature for JW.

That was a long story...hope you more or less understand it.

Appriciate your replies.

JW Player

User  
0 rated :

Ron,

Perhaps you have a point - you seem to know what you're saying and the script just didn't work - it worked in the beginning but not any more so maybe you're right about the instability of gdata or whatever - add me through my website and we can discuss it more; also I will of course post on this thread if I come up with a solution... Hmm... The trick is probably to make a long list of separate shorter YT playlists but I just dunno how, adding them manually is way too much hassle - something to consider too is the fact that it's not easy to find anything on this subject on the interweb, which could be a sign that there's actually no solution but you know what let's keep working on this till we find one.

JW Player

User  
0 rated :

CS,

Your script actually worked to begin with so it seemed like you were close to solving this issue permanently, not only for me but I'm sure there are tons of people who would like to know how to do this.

JW Player

User  
0 rated :

.

@ Pongy

The biggest problem is that...of all 3rd-party api-players i have seen
the designers dont have enough real-life experience with youtube
They assume that youtube is perfect..they dont know its full of bugs
or complications..they obviously also dont look at it from a real users
point of view.

Most of all they dont listen to those that do have real experience.
As a result everytime i find a player that seem to do it right
i quickly discover that there's still a lot of problems.
As soon as i mention them...the designers become irritated..because
my remarks actually show that their players are not good (enough) yet.

So i become irritated..and they become irritated too
so that is a dillemma...unfortunately none of them is prepared to
even accept any input from some experienced and real-life user.
They prefer to ignore you...so they can go-on selling their product
to those that have little real experience...and that dont have to much demands
Like good working (long)playlist...in HD format.

If you wanted to produce something like a on-demand Tv-station
with a 1000 videos in long playlists @HD ...you cant, because
no player can do it...believe me i am looking for it almost 3 years now
tested 10 players that seemed to come close..but in the end they all fail.

What is you website ?

.

JW Player

User  
0 rated :

Ron,

Ah, well the guys at this forum have been supportive so please don't fret too much - my website is aoioe.tk/video.html by the way - hmm, yeah, I believe YT may also have its reasons not wanting to allow anyone to embed very long playlists, perhaps they're worried about loosing ad revenue or brand value or something, but you never know perhaps one day there will be a solution to this matter.

JW Player

User  
0 rated :

(I also have been trying to do this for a very long time on an on-off basis BUT on the 20th of July when I tested the script above it worked - I can't remember exactly but I'm quite sure I saw more than 50 entries, so I definitely had a notion that a solution was very close)

JW Player

User  
0 rated :

I think the JW player can play a list of YT videos just fine, the trick is creating a long playlist from many short ones which is more of a PHP related question so the problem does not lie with the JW player or Longtail Video.

I'm currently working on this on some other forums as well, I'll let you know if something interesting comes up but don't get your hopes up just yet.

JW Player

User  
0 rated :

Hi can I request a working PHP codes, the codes on this forums is not working, the link are also unreachable.

Thanks

JW Player

User  
0 rated :

I second that, but I think it's unrealistic that we will get the code anytime soon.

JW Player

User  
0 rated :

bc.. <?php

// YouTube_Playlist_XSPF-3.1.php 20100912
// call with: http://my.site.org/YouTube_Playlist_XSPF-3.1.php?playlistid=B8D6FA74D3F2629C

// playlists need to be updated at least every 2 hours
$update_interval = 2;

// change this path to your cache directory on your server
$cachedirectory = '/nginx/html/cache/';

// for command line argument passing
if(isset($_SERVER['argv'][1]))
{
$_GET['playlistid'] = $_SERVER['argv'][1];
}


// debug('Playlist ID', $_GET['playlistid']);
// exit;


// use your playlist ID here as the default
$playlistid = (isset($_GET["playlistid"])) ? strval($_GET["playlistid"]) : "B8D6FA74D3F2629C";

// max-results is limited to 50 per request
$playlisturl1 = "http://gdata.youtube.com/feeds/api/playlists/" . $playlistid . "?start-index=1&max-results=50";
$playlisturl2 = "http://gdata.youtube.com/feeds/api/playlists/" . $playlistid . "?start-index=51&max-results=50";
$playlisturl3 = "http://gdata.youtube.com/feeds/api/playlists/" . $playlistid . "?start-index=101&max-results=50";
$playlisturl4 = "http://gdata.youtube.com/feeds/api/playlists/" . $playlistid . "?start-index=151&max-results=50";

// create cache filename
$patterns = array('#gdata#', '#/#', '#:#', '#\.#', '#http#', '#youtube#', '#com#', '#feeds#', '#api#', '#playlists#', '#\?start-index=1&max-results=50#');
$replacements = array( '', '', '', '', '', '', '', '', '', 'playlists_', '');
$filename = preg_replace($patterns, $replacements, $playlisturl1);


// debug(' Playlist ID', $playlistid);
// debug(' Playlist URL 1', $playlisturl1);
// debug(' Playlist URL 2', $playlisturl2);
// debug(' Playlist URL 3', $playlisturl3);
// debug(' Playlist URL 4', $playlisturl4);
// exit;


for ($i=0; $i < $update_interval; $i++)
{
$cachefilename = (date('YmdH') - $i) . '_' . $filename . ".xml";
if(file_exists($cachedirectory . $cachefilename))
{
if(!isset($_SERVER['argv'][1]))
{
header ("content-type: text/xml");
print file_get_contents($cachedirectory . $cachefilename);
}
exit;
}
}

$cachefilename = date('YmdH') . '_' . $filename . ".xml";


// debug('Cache Filename', $cachefilename);
// exit;


$playlistcontent1 = file($playlisturl1);
$playlistcontent2 = file($playlisturl2);
$playlistcontent3 = file($playlisturl3);
$playlistcontent4 = file($playlisturl4);
$playlistcontent = array_merge($playlistcontent1, $playlistcontent2, $playlistcontent3, $playlistcontent4);

$contentstring = "";

foreach($playlistcontent as $value)
{
$contentstring .= rtrim($value);
}

$contentarray = explode("<entry>", $contentstring);


// debug('Playlist Content', $playlistcontent);
// debug('Content String', $contentstring);
// debug('Content Array', $contentarray);
// exit;


$track = 0;
$type = "";

// construct XSPF playlist headers
$playlist = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
$playlist .= "<playlist version=\"1\" xmlns=\"http://xspf.org/ns/0/\">\n";
$playlist .= " <trackList>\n";

// construct XSPF playlist tracks
while($junk = next($contentarray))
{
$track++;
$playlist .= " <track>\n";

if((preg_match('/<title>(.*?)<\/title>/', $junk, $match)) || (preg_match('/<title type=\'text\'>(.*?)<\/title>/', $junk, $match)))
{
$playlist .= " <title>" . $match[1] . "</title>\n";


// debug('Playlist', $playlist);
// debug('Match[1]', $match[1]);
// exit;


}

if(preg_match('/<name>(.*?)<\/name>/', $junk, $match))
{
$playlist .= " <author>" . $match[1] . "</author>\n";


// debug('Playlist', $playlist);
// debug('Match[1]', $match[1]);
// exit;


}

// <media:thumbnail url='http://img.youtube.com/vi/izoZ-hjbKJQ/0.jpg
if(preg_match('/<media:thumbnail url=.*?<media:thumbnail url=.*?<media:thumbnail url=.*?<media:thumbnail url=\'(.*?)0.jpg/', $junk, $match))
{
$playlist .= " <image>" . $match[1] . "0.jpg</image>\n";


// debug('Playlist', $playlist);
// debug('Match[1]', $match[1]);
// exit;


}


//...debugging
// preg_match('/<media:content url=\'(.*?)\?f=playlists/', $junk, $match);
// print $junk;
// print_r($match);


// <media:content url='http://www.youtube.com/v/5GE82tqcYYQ?f=playlists&app=youtube_gdata' type='application/x-shockwave-flash' medium='video' isDefault='true' expression='full' duration='723' yt:format='5'/>
// <media:content url=\'(.*?)\?f=playlists&app=youtube_gdata' type='application/x-shockwave-flash' medium='video' isDefault='true' expression='full' duration='723' yt:format='5'/>
if(preg_match('/<media:content url=\'(.*?)\?f=playlists/', $junk, $match))
{
$playlist .= " <location>" . $match[1] . "</location>\n";


// debug('Playlist', $playlist);
// debug('Match[1]', $match[1]);


}

$playlist .= " <meta rel=\"type\">youtube</meta>\n";
$playlist .= " <annotation>Track " . $track . "</annotation>\n";
$playlist .= " </track>\n";


// debug('Playlist', $playlist);
// if($track > 4) break;


}

// construct XSPF playlist footers
$playlist .= " </trackList>\n";
$playlist .= "</playlist>\n";


if(!isset($_SERVER['argv'][1]))
{
header ("content-type: text/xml");
print $playlist;
}

// check cache - write to cache
if(!file_exists($cachedirectory . $cachefilename))
{
$fh = fopen($cachedirectory . $cachefilename, 'a');

fwrite($fh, $playlist);

fclose($fh);
}

// cleanup cache
@$directory_handle = dir($cachedirectory);

if($directory_handle)
{
while (false !== ($currentfile = $directory_handle->read()))
{
// 2010091201_playlists_B4EF96652BFE5853.xml
if(preg_match('/(\d{10})_playlists_.*?.xml/', $currentfile, $match))
{
$currentdate = date('YmdH');


// debug('Current Date', $currentdate);
// debug('Current File', $currentfile);
// debug(' Match[1]', $match[1]);
// exit;

// if file is older than current hour - update interval, delete file
if($match[1] < $currentdate - $update_interval + 1)
{
unlink($cachedirectory . $currentfile);
}
}
}
$directory_handle->close();
}


function debug($title, $value)
{
global $debug_output;

print "<pre>";
if(is_array($value))
{
print $title . ":\n";
print_r($value);
}
else
{
print $title . ": " . $value;
}
print "</pre>\n";
}

?>



JW Player

User  
0 rated :

There's a code! I haven't had time to test it yet but it definitely looks like something.

JW Player

User  
0 rated :

Hi can you provide a text link? when I copy the code and edit in PHP designer I got this error on line 141 if(preg_match('/<media:content url=\'(.*?)\?f=playlists/', $junk, $match))
{
$playlist .= " <location>" . $match[1] . "</location>\n";

I'm not a PHP programmer. Please.

Thanks

Ethan Feldman

JW Player Support Agent  
0 rated :

@Ricky – What are you looking to do with this code? Where is this code being run ?

JW Player

User  
0 rated :

replace all occurrences of
with a newline (carriage return/linefeed)

JW Player

User  
0 rated :

Here we go...

This question has received the maximum number of answers.