🎞️
YouTubeの動画サムネイルをWordPressの投稿サムネイルとして自動挿入するカスタムフィールドを作成するコード
前置き
僕がこんなもの作らなくてもこういうプラグインがある。
(今回は要件に合わなかった)
Featured Video Plus
Video Thumbnails Reloaded
コード
functions.php
<?php
// -----------------------------------
// YouTubeの動画サムネイルをWordPressの投稿サムネイルとして自動挿入する
// -----------------------------------
// カスタムフィールドを作る
// [参考]https://camel-press.com/media/customfield/
add_action('admin_menu', 'create_custom_fields');
function create_custom_fields()
{
add_meta_box(
'youtube-settings', //編集画面セクションID
'YouTubeのリンク', //編集画面セクションのタイトル
'insert_custom_fields', //編集画面セクションにHTML出力する関数
'post', //投稿タイプ名
'normal' //編集画面セクションが表示される部分
);
}
// 入力フォームの作成と、スクリプトの挿入
function insert_custom_fields()
{
global $post;
// 登録してある値を取得(無ければ空文字を代入)
$youtube_url = get_post_meta($post->ID, 'youtube-url', true) ?: "";
$youtube_thumbnail = get_the_post_thumbnail_url($post -> ID) ?: "";
?>
<form method="post" action="admin.php?page=site_settings">
<table class="form-table cptui-table">
<tbody>
<tr>
<th scope="row"><label for="set-url">URL</label> <span class="required">*</span></th>
<td>
<input aria-required="true" id="set-url" name="youtube-url" required="true" type="text" value="<?php echo $youtube_url;?>">
</td>
</tr>
<tr>
<th scope="row"><label for="preview-thumbnail">サムネイル</label></th>
<td>
<div id="preview-thumbnail">
<?php if($youtube_thumbnail): ?>
<img src="<?php echo $youtube_thumbnail?>" alt="" width="500">
<?php else:?>
<p>未取得</p>
<?php endif;?>
</div>
<input type="hidden" id="set-thumbnail" name="youtube-thumbnail" value="<?php echo $youtube_thumbnail;?>">
</td>
</tr>
</tbody>
</table>
<script>
// サムネイルを取得
// [出典]https://zenn.dev/attt/articles/get-yt-thumbnail
window.addEventListener("DOMContentLoaded", () => {
const input = document.getElementById("set-url");
let _box = document.getElementById("preview-thumbnail");
let _send_box = document.getElementById("set-thumbnail");
// 正規表現で動画idを切り出す
let regex = /(https?:\/\/)?(((m|www)\.)?(youtube(-nocookie)?|youtube.googleapis)\.com.*(v\/|v=|vi=|vi\/|e\/|embed\/|user\/.*\/u\/\d+\/)|youtu\.be\/)([_0-9a-z-]+)/i;
input.addEventListener("input", ()=> {
let _videoUrl = input.value;
if(_videoUrl) {
let _videoId = _videoUrl.match(regex)[8];
(async () => {
const thumbnail = await getYtThumbnail(_videoId);
_send_box.value = thumbnail;
let _img = document.createElement("img");
_img.setAttribute("src", thumbnail);
_img.setAttribute("width", "500");
_box.innerHTML = "";
_box.appendChild(_img);
})();
}
});
});
const THUMB_TYPES = ['maxresdefault.jpg','sddefault.jpg','hqdefault.jpg','mqdefault.jpg','default.jpg'];
const getYtThumbnail = async (videoId) => {
// 画像をロードする処理
const loadImage = (src) => {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = (e) => resolve(img);
img.src = src;
});
};
for (let i = 0; i < THUMB_TYPES.length; i++) {
const fileName = `https://img.youtube.com/vi/${videoId}/${THUMB_TYPES[i]}`;
const res = await loadImage(fileName);
// ダミー画像じゃなかったら(横幅が121px以上だったら)
// もしくは、これ以上小さい解像度が無かった場合は、このURLで決定
if (
!THUMB_TYPES[i + 1]
|| (res).width > 120
) {
return fileName;
}
}
};
</script>
</form>
<?php
}
// 保存する
function save_custom_fields($post_id)
{
if($_POST['youtube-thumbnail'] && $_POST['youtube-url']) {
// サムネイルを保存
$media_url = $_POST['youtube-thumbnail'];
$tmp = download_url($media_url);// 画像をDLし、一時ファイルに保存
// 手動でサムネイルを差し替えたときのエラーハンドリング
if (!is_wp_error($tmp)) {
// ファイルをアップロードディレクトリに移動
$upload_dir = wp_upload_dir();
$file_extension = pathinfo($media_url, PATHINFO_EXTENSION);
$file_name = str_replace('.', '', microtime(true)) . '.' . $file_extension; // ユニークなファイル名にする(キャッシュ対策)
$uploaded_file = $upload_dir['path'] . '/' . $file_name;
rename($tmp, $uploaded_file);
// 添付ファイルの情報を設定
$media_title = 'thumbnail';
$media_description = 'from : youtube';
$file_type = wp_check_filetype($file_name, null);
$attachment = array(
'post_mime_type' => $file_type['type'],
'post_title' => $media_title,
'post_content' => $media_description,
'post_status' => 'inherit',
'timestamp' => time()
);
// メディアを挿入し、添付ファイルとして投稿に関連付ける
$attach_id = wp_insert_attachment($attachment, $uploaded_file, $post_id);
// 添付ファイルのメタデータを生成
require_once(ABSPATH . 'wp-admin/includes/image.php');
$attach_data = wp_generate_attachment_metadata($attach_id, $uploaded_file);
wp_update_attachment_metadata($attach_id, $attach_data);
// 投稿のサムネイルにアップロードした画像を設定
set_post_thumbnail($post_id, $attach_id);
}
// カスタムフィールドを保存
update_post_meta($post_id, 'youtube-url', $_POST['youtube-url']);
}
}
add_action('save_post', 'save_custom_fields');
?>
参考コード
コード内にもあるけどあらためて書いておく。
カスタムフィールドを自作する方法【プラグインなし】
ブクマしていつも見てる【JS】YouTubeの動画IDからなるべく大きい解像度のサムネイルを取得する方法(API使わずに)
面倒な部分を考えずに済んで助かったちなみに正規表現でYouTubeのURLから動画idを切り出すコードは
youtube video id regex
で調べるといっぱい出てくる。
考慮ポイント
- 手動でサムネイルを差し替えても大丈夫
- ファイル名を重複しないよう(UNIXTIME)にすることでサーバーキャッシュを回避(同じファイル名で画像を上げると、消した画像が表示される現象が起こる)
残念ポイント
- 動画のサムネが変わっても投稿には反映されない(その代わりYouTubeでエラーが起きたり動画が消えたりしてもサムネが消えないし、ページロードも早い)
Discussion