YouTube動画をサムネイルでリンクする

投稿日:

時々YouTube動画をリンクしてたりします。従来はYouTubeが提供している「動画の埋め込み」、すなわちiflameの埋め込みプレーヤーを置いてました。

↓こーゆーやつ。

<iframe width="560" height="315" src="https://www.youtube.com/embed/caqbsA-oPNA" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

ただこれも数が多くなるとちょっとうっとおしいのでなんとかならんかなーと思ってました。具体的には「単なるリンクにならんかな」と。

YouTube動画のサムネイル画像自体は簡単に取得できるのですが、画像だけでは

・これが動画のサムネイルであること
・このリンクがYouTubeへのリンクであること

が見る人にわかりません。

↑単なる画像にしか、見えない(^_^;)

で、「動画っぽい再生ボタンを合成すればわかるのでは?」と思いつき、まずスタイルシートで再生ボタンを重ねてみました。

.play-button {
position: relative;
top: -130px;
left: -330px;
opacity: 0.9;
}

↑こんな感じで「サムネイルに再生ボタン画像を重ねる」ことはできるんだけど、この「ピクセル単位で画像位置を指定する」やり方は画像が伸びたり縮んだりするレスポンシブ対応とすごく相性が悪く、デバイス替えるとめちゃめちゃずれちゃう(^_^;)

ということで、もうサムネイル画像はサーバ側で合成することにします。

ただサムネイルを取得して合成するだけなら別にいらんのですが、どうせなら動画情報も取得して色々合成できた方が良いかもということで、YouTube APIから動画情報をもらってくるようにします。

$google = 'https://www.googleapis.com/youtube/v3/videos?part=id,snippet&id=';

$google .= $id . '&key=' . $API_KEY;

$json = file_get_contents($google);

$arr = json_decode($json, TRUE);

$items = $arr["items"];

この$itemsが空なら該当する動画はない→終了。

該当動画が存在すれば

"items": [
{
"kind": "youtube#video",
"etag":,
"id":,
"snippet": {
"publishedAt":,
"channelId":,
"title":,
"description":,
"thumbnails": {
"standard": {
"url":,
"width": 640,
"height": 480
},

みたいな感じでずらずら情報が出てくるので、PHPで

$src_image = imagecreatefromjpeg($img_url);

$icon = imagecreatefrompng($icon);

$button = imagecreatefrompng($button);

$thumbnail_image = imagecreatetruecolor($new_width, $new_height);

$sx = imagesx($button);

$sy = imagesy($button);

$x = ($new_width / 2) - ($sx / 2);

$y = ($new_height / 2) - ($sy / 2);

//画像リサイズ
imagecopyresampled($thumbnail_image, $src_image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);

//画像合成
imageLayerEffect($thumbnail_image, IMG_EFFECT_ALPHABLEND);

//再生ボタン合成
imagecopy($thumbnail_image, $button, $x, $y, 0, 0, $sx, $sy);

とかやれば「定型サイズで合成がズレないサムネイル画像」が出来ます。

毎回毎回APIを呼び出すのもアレなんでキャッシュを作ったりタイトルを合成したり他にもいくつかやってることはあるんですが、基本的にはこれだけ。

そしてPHPから画像を出力する場合、そのままだとブラウザキャッシュが効かないので

PHPから画像を送信する際にキャッシュを有効にしておく

のようにheaderでLast-Modifiedを返す/IF_MODIFIED_SINCEが効くようにしておきます。

$last_modified = filectime($cache_file);

if(isset($_SERVER["HTTP_IF_MODIFIED_SINCE"])){
$str_time = $_SERVER["HTTP_IF_MODIFIED_SINCE"];
$last_modified_since = strtotime($str_time);

if($last_modified_since == $last_modified){
header("HTTP/1.1 304 image not modified");
header('Pragma: cache');
header("Cache-Control: max-age=".(60*60*24));
exit;
}

}

↑24時間使ってねのコード。

あ、なんか濁点のついたカタカナやひらがなは文字と濁点が2文字に分離することがあったので、

$title = normalizer_normalize( $title, Normalizer::FORM_C );

と正規化処理を挟んでます。

Normalizer::normalize [PHP]


こうしたリンクをいちいち手で書くのも面倒なんで、動画URLを入力するとタグのかたまりを出力してくれるツールも作りました。

230520_02.jpg

変換ボタンを押すと

<div class="youtube-thumbnail">
<a class="youtube" href="https://www.youtube.com/watch?v=caqbsA-oPNA" target="_blank">
<img class="youtube-image" src="https://crusherfactory.net/~yas_/youtube_image.php?id=caqbsA-oPNA" alt="FULLY RUSTED FRAME RESTORED & BUILT" width="500" height="375">
</a>
<p class="youtube-title"><a href="https://www.youtube.com/watch?v=caqbsA-oPNA" target="_blank">FULLY RUSTED FRAME RESTORED & BUILT</a> [YouTube]</p>
</div>

こうなって貼り付けるだけ→ラクチン(^_^)