I am currently adapted a code to my website's use but now I would like to change some of its format but it has been a harder task than expected. My code right now is displaying the latest video. But my goal at the moment is to have the code display the videos *thumbnail pic, *video description and *total views. Below is my code, If you think there is a better way to approach this then I am open for suggestions:
<?
error_reporting(E_ALL);
$feedURL = 'http://gdata.youtube.com/feeds/api/users/USERNAME/uploads?max-results=20';
$sxml = simplexml_load_file($feedURL);
$i = 0;
foreach ($sxml->entry as $entry) {
$media = $entry->children('media', true);
$url = (string)$media->group->player->attributes()->url;
$index = strrpos($url, "&");
$url = substr($url, 0, $index);
$index = strrpos($url, "watch");
$url = substr($url, 0, $index) . "v/" . substr($url, $index + 8, strlen($url) - ($index + 8));
echo '<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="400" height="250" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="' . $url . '" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="400" height="250" src="' . $url . '" allowscriptaccess="always" allowfullscreen="true"></embed></object>';
break;
}
?>
To build on Chris Willenbrock's work, in order to simplify the code a little and save yourself some overhead (an extra entries 20-$count across the wire, extra explode on 20-$count entries that won't be displayed anyway):
//SETTINGS
$channel_name = 'mychannelname';//Be sure to change this to your channel
$count = 8;//# of videos you want to show (MAX = 20)
$em_width = 420;//width of embedded player
$em_height = 315;//height of embedded player
$wrap_class = 'video';//class name for the div wrapper
//The output...
$sxml = simplexml_load_file("http://gdata.youtube.com/feeds/api/users/$channel_name/uploads?max-results=$count");
foreach ($sxml->entry as $entry) {
$vidKey = substr(strrchr($entry->id,'/'),1);
echo "
<div class=\"$wrap_class\">
<iframe width=\"$em_width\" height=\"$em_height\" src=\"http://www.youtube.com/embed/$vidKey\" frameborder=\"0\" allowfullscreen></iframe>
</div>
";
}
I don't enjoy working with XML and avoid it where I can, so here is another option that uses JSON. Also, note that by switching to v2 of the API here we get much cleaner access to the video key, as well as the other meta-data that the original poster was asking for:
//The output...
$api_v2 = "http://gdata.youtube.com/feeds/api/users/$channel_name/uploads?max-results=$count&v=2";
foreach (json_decode(file_get_contents("$api_v2&alt=json"))->feed->entry as $entry) {
// meta information
$title = $entry->title->{'$t'};
$description = $entry->{'media$group'}->{'media$description'}->{'$t'};
$views = $entry->{'yt$statistics'}->viewCount;
$thumbnails = $entry->{'media$group'}->{'media$thumbnail'};
// few different thumbnail image choice here:
// 0 => default image, low res - "default"
// 1 => default image, medium res - "mqdefault"
// 2 => default image, higher res - "hqdefault"
// 3 => first frame of vid, low res - "start"
// 4 => middle frame, low res - "middle"
// 5 => last frame, low res - "end"
$thumb_img = $thumbnails[1]; // I'll go with default, medium res
echo "
<!-- meta information output - format to taste -->
<div>
<img src='$thumb_img->url' style='float: left; margin-right: 10px;' width='$thumb_img->width' height='$thumb_img->height' alt='{$thumb_img->{'yt$name'}}'>
<b>Title:</b> $title<br><br>
<b>Description:</b> $description<br><br>
<b>Views:</b> $views
<br style='clear: left;'>
</div>
<div class=\"$wrap_class\">
<iframe width=\"$em_width\" height=\"$em_height\" src=\"{$entry->content->src}\" frameborder=\"0\" allowfullscreen></iframe>
</div>
";
}
Add
var_dump($entry);exit;
at the first line inside the foreach code, then take a look at the output and search for your thumbnail images. Then you have to follow the path like it was done with the URL ($entry->children(..) and $media->path->to->thumbnail)
Youtube has updated their embed methods and api output, so I took the opportunity to update the script. You can probably just move all of the settings into the core part of the script, but I figured I'd pull it out to make it easier to follow. Hope this helps:
//SETTINGS
$channel_name = 'mychannelname';//Be sure to change this to your channel
$count = 8;//# of videos you want to show (MAX = 20)
$em_width = 420;//width of embeded player
$em_height = 315;//height of embeded player
$wrap_class = 'video';//class name for the div wrapper
//The output...
error_reporting(E_ALL);
$feedURL = 'http://gdata.youtube.com/feeds/api/users/'.$channel_name.'/uploads?max-results=20';
$sxml = simplexml_load_file($feedURL);
$i = 1;
foreach ($sxml->entry as $entry) {
$vidUrl = explode("/", $entry->id);
$vidKey = $vidUrl[6];
if ($i <= $count ) :
echo '
<div class="'.$wrap_class.'">
<iframe width="'.$em_width.'" height="'.$em_height.'" src="http://www.youtube.com/embed/'.$vidKey.'" frameborder="0" allowfullscreen></iframe>
</div>
';
endif;
$i++;
}
Related
As most people know, wordpress uses oembed to fetch the embed code for videos when adding a youtube video to a post. For example, pasting:
https://www.youtube.com/watch?v=pATcvr3zAhg
Would output this in the html:
<iframe width="420" height="315" src="https://www.youtube.com/embed/pATcvr3zAhg" frameborder="0" allowfullscreen></iframe>
I want to change this markup so it uses fancybox and an image, so my markup should look like this:
<a class="fancybox.iframe various" href="VIDEO SOURCE"><img src="IMAGE HERE"></a>
I was using this code which originally replaced the video with an image and when clicked, changed to the video - however, I want to modify this code now so that it outputs the markup above.
add_filter( 'oembed_dataparse', function($str, $data, $url) {
if ( ($yt = $data->provider_name == 'YouTube') || ($vm = $data->provider_name == 'Vimeo') )
{
if($yt) $html = str_replace('feature=oembed', 'feature=oembed&autoplay=1', $str);
else $html = str_replace('" width=', '?autoplay=1" width=', $str);
$html = htmlentities($html, ENT_QUOTES);
$img = $data->thumbnail_url;
$title = esc_attr($data->title);
return '<img src="'. $img . '" onclick="this.outerHTML=\'' . $html . '\'" title="' . $title . '">';
}
return $str;
}, 10, 3);
i have a posting feature on my site that can embed links and youtube videos. the problem is, that the two clash together, and the youtube iframe ends up being a 404 page on my site. my codes for the youtube videos and links are below, but im not sure how to stop them from combining and ruining it.
by combining, i mean this http://www.youtube.com/watch?v=VhqiT2nWCVU turns to
<iframe src="http://www.youtube.com/watch?v=VhqiT2nWCVU">
which then turns into
<iframe src="">
sorry if i am unclear in any way. my codes are below.
function youtube($string)
{
return preg_replace(
'#(http://(www.)?youtube.com)?/(v/|watch\?v\=)([-|~_0-9A-Za-z]+)&?.*?#i',
'<iframe title="YouTube video player" width="480" height="390" src="http://www.youtube.com/embed/$4?rel=0" frameborder="0" allowfullscreen></iframe>',
$string
);
}
$posted = youtube($posted);
$rexProtocol = '(https?://)?';
$rexDomain = '((?:[-a-zA-Z0-9]{1,63}\.)+[-a-zA-Z0-9]{2,63}|(?:[0-9]{1,3}\.){3}[0-9]{1,3})';
$rexPort = '(:[0-9]{1,5})?';
$rexPath = '(/[!$-/0-9:;=#_\':;!a-zA-Z\x7f-\xff]*?)?';
$rexQuery = '(\?[!$-/0-9:;=#_\':;!a-zA-Z\x7f-\xff]+?)?';
$rexFragment = '(#[!$-/0-9:;=#_\':;!a-zA-Z\x7f-\xff]+?)?';
// Solution 1:
function callback($match)
{
// Prepend http:// if no protocol specified
$completeUrl = $match[1] ? $match[0] : "http://{$match[0]}";
return '<a href="' . $completeUrl . '">'
. $match[2] . $match[3] . $match[4] . '</a>';
}
$posted = preg_replace_callback("&\\b$rexProtocol$rexDomain$rexPort$rexPath$rexQuery$rexFragment(?=[?.!,;:\"]?(\s|$))&",
'callback', $posted);
A popular solution to this problem is to use placeholders. On your first pass you turn all YouTube links into a placeholder, for example:
{{youtube:VhqiT2nWCVU}}
After that you run your normal link converter. And at the end your run yet another regex to turn all your palceholders into youtube embeds.
I'm not sure when, but at some point my YouTube searching method stopped working, it has worked for years but both the API and the preferred method of displaying embedded video has changed. I've looked at the official Google docs and I have the option of using Zend or the currently in development Version 3 of the Google API, these are a lot larger codebases than what I was currently using.
I've tried debugging my code and may eventually get it working again, should I just scrap it and integrate the more official PHP codebase into my project. This was is where my method sits, it finds data, but I don't seem to display any videos...
public function embeddableVideoClipFor($searchString)
{
// Previous experience revealed that video search is not perfect, but we're just going to giver and create an embedded player with the
// top result or return NULL
// I used this as a guide to build my embedded player http://code.google.com/apis/youtube/youtube_player_demo.html
$embeddableVideoClipHTML = NULL;
// Further details on searching YouTube http://www.ibm.com/developerworks/xml/library/x-youtubeapi/
// This was working well for over two years but now I'm getting no videos, I may have been throttled or more likely the API has changed...
// Before switching to Zend or going to switch to version 3.0 of Google/YouTube API I should try and debug...
$vq = $searchString;
$vq = preg_replace('/[[:space:]]+/', ' ', trim($vq));
$vq = urlencode($vq);
$feedURL = 'http://gdata.youtube.com/feeds/api/videos?q=' . $vq . '&safeSearch=none&orderby=viewCount&v=2'; // Added version two tag...
print_r($feedURL);
// read feed into SimpleXML object
try
{
$youTubeXML = simplexml_load_file($feedURL);
}
catch(Exception $e)
{
// This rarely throws an error, but when it does, I just want to pretend I can't find a video clip
$youTubeXML = NULL;
}
print("<pre>");
print_r($youTubeXML);
print("</pre>");
if(($youTubeXML != NULL) && ( ! empty($youTubeXML->entry->link[0]['href'])))
{
$videoLink = $youTubeXML->entry->link[0]['href']; // This is not enough, I need to trim the beginning and end off this to just get the video code
$trimedURL = str_replace('http://www.youtube.com/watch?v=', '' , $videoLink);
$videoCode = str_replace('&feature=youtube_gdata', '', $trimedURL);
// $embeddableVideoClipHTML = '<object style="height: 390px; width: 640px"><param name="movie" value="http://www.youtube.com/v/' . $videoCode . '"><param name="allowFullScreen" value="true"><param name="allowScriptAccess" value="always"><embed src="http://www.youtube.com/v/' . $videoCode . '?version=3" type="application/x-shockwave-flash" allowfullscreen="true" allowScriptAccess="always" width="640" height="390"></object>';
// $embeddableVideoClipHTML = '<iframe id="ytplayer" type="text/html" width="640" height="360" src="https://www.youtube.com/embed/' . $videoCode . '"frameborder="0" allowfullscreen>';
// Version 3
$embeddableVideoClipHTML = '<object width="640" height="360"><param name="movie" value="https://www.youtube.com/v/' . $videoCode . '?version=3"></param><param name="allowFullScreen" value="true"></param><param name="allowScriptAccess" value="always"></param><embed src="https://www.youtube.com/v/' . $videoCode . '?version=3" type="application/x-shockwave-flash" allowfullscreen="true" allowScriptAccess="always" width="640" height="360"></embed></object>';
}
return $embeddableVideoClipHTML;
}
I'm not sure why, because I did try it, but switching to the iFrame, ie this line of code:
// $embeddableVideoClipHTML = '<iframe id="ytplayer" type="text/html" width="640" height="360" src="https://www.youtube.com/embed/' . $videoCode . '"frameborder="0" allowfullscreen>';
Works now, but I still wonder if I should jump through hoops to use one of the more official PHP frameworks, I really only use this one method to access the Google/YouTube api, it isn't a big part of my mashup, but I like it for movie trailers and song lyric quotations.
I have an HTML file that has external assets on a secure server that needs a url generated in order to load. I can load the HTML file fine, but none of the images will load. Relative paths wont work. I need to pass the image src attribute to my generateURL method and replace the current relative src paths with my generated url. An example HTML file I need to replace the tags in would be:
<img id="Im0" src="slide1page1/img/1/Im0.png" alt="Im0" width="720" height="540" style="display: none" />
<img id="Im1" src="slide1page1/img/1/Im1.png" alt="Im1" width="136" height="60" style="display: none" />
<img id="Im2" src="slide1page1/img/1/Im2.png" alt="Im2" width="669" height="45" style="display: none" />
My php script that I load the page through is:
<?php
function generateURL($target,$seconds)
{
$secret = "mysecretpasscode";
$end = time() + $seconds;
$url = $target . "?e=" . $end;
$toHash = $secret . $url;
$secure = $url . "&h=" . md5($toHash);
return $secure;
}
$id = $_POST['id'];
$loc = $_POST['loc'];
$url = $loc . "slide" . $id . ".html";
$secure = generateURL($url,600);
$page = file_get_contents($secure);
?>
if I echo $page, I can see the page as if I just loaded an html page (but no images). What I need to do before that is find all the src tags in the HTML and run them through my generateURL method so I can generate the correct URL with proper hashing to load. I am thinking a str_replace will work, but I am not familiar enough with regex to continue. Any help would be appreciated.
First have a look at this answer: RegEx match open tags except XHTML self-contained tags
Though I think you could use PHP's preg_replace_callback as follows:
src_regex = "/src=\"([^\"]+\/";
preg_replace_callback(src_regex, generateURL, html);
Do take into account that the second parameter (generateURL) must be a function with only a single argument, take a look at this page.
A html parser would be better. Provided you've selected all the tags, you can extract the relative path with the function below.
$u = '<img id="Im0" src="slide1page1/img/1/Im0.png" alt="Im0" width="720" height="540" style="display: none" />';
$v = explode(" ", $u);
$x = explode("=", $v[2]);
echo str_replace("\"", "", $x[1]);
Outputs
slide1page1/img/1/Im0.png
<?php
$i = 0;
$page = get_the_content();
$doc=new DOMDocument();
$doc->loadHTML($page);
$xml=simplexml_import_dom($doc);
$images=$xml->xpath('//img');
foreach ($images as $img) {
list($width, $height, $type, $attr) = getimagesize($img['src']);
if ($height > 149 ) {
echo '<img src="' . $img['src'] . '" alt=" ' . $img['alt'] . ' - funny and hot pictures" title=" ' . $img['title'] . ' - funny fail picture dump" onerror=\'this.style.display="none" \'><br>';
$i++;
if ($i == 3 ) { break;}
}
else
{
// don't display
}
}
?>
I replaced the "<?php the_content(); ?>" piece of code with the one above. It's supposed to strip out all of the text in my post and just leave the images which it does nicely. But when I embed a video the php breaks. How would I allow posts to show youtube videos?
You should look into using custom fields:
http://codex.wordpress.org/Custom_Fields
There is a great plugin that creates good admin control panels for them too:
http://wordpress.org/extend/plugins/advanced-custom-fields/
You could use a custom field to specifically put a video into the page.
Is there a particular reason you want to strip the text out of the post? - e.g. could you just not put text in the post at all? - or could the text be put into the excerpt instead, or into a custom field so that you don't have to over complicate the output code?