Cum să obții automat imaginea YouTube pentru thumbnail?
Am un tip de postare personalizată care acceptă un fragment HTML de embed YouTube, titlu și o imagine reprezentativă. În prezent, caut manual o imagine pentru imaginea reprezentativă, dar ideal ar fi să pot descărca și redimensiona automat primul cadru al videoclipului bazat pe URL-ul videoclipului în timpul procesului de salvare al postării. Dacă este făcut corect, tipul meu de postare ar putea necesita doar link-ul și ar putea obține atât imaginea cât și codul de embed din acesta.
De exemplu, dacă link-ul videoclipului este http://www.youtube.com/watch?v=2Jnpi-uBiIg valoarea parametrului v ar fi extrasă și folosită pentru a descărca imaginea de la http://img.youtube.com/vi/2Jnpi-uBiIg/0.jpg.
Sunt foarte nou în dezvoltarea WordPress, dar ceva îmi spune că ar trebui să mă uit după hooks (dacă le înțeleg corect).

Salut @Jonathan Sampson:
Deși aceasta nu este exact ceea ce ai cerut, ar putea fi o soluție viabilă și este oferită gratuit de WordPress.com datorită tweet-ului @yoast de dimineață, când a menționat acest articol de blog:
Practic, poți folosi URL-ul generatorului de capturi de ecran al WordPress.com în această formă (care, conform articolului de blog, Matt a părut să aprobe utilizarea gratuită):
https://s.wordpress.com/mshots/v1/{URL-codificat}?w={lățime}
Luând URL-ul tău de mai sus:
Și apoi codificându-l URL pentru a-l folosi cu generatorul de capturi de ecran, obții un URL care arată astfel (pentru o lățime de 400px):
https://s.wordpress.com/mshots/v1/http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3D2Jnpi-uBiIg?w=400
Și, desigur, urmează cum arată captura de ecran (am copiat captura de ecran pentru posteritate, astfel încât să nu se schimbe chiar dacă serviciul WordPress este modificat, în loc să includ un link direct către serviciu pentru a afișa imaginea.) Nu sunt sigur de ce a capturat doar videoclipul și nu întreaga pagină, dar videoclipul este și mai bun pentru ceea ce dorești:
(sursa: mikeschinkel.com)
Desigur, prima dată când faci o cerere HTTP GET către URL, nu va returna o captură de ecran, deoarece serverele WordPress.com trebuie mai întâi să captureze captura de ecran, ceea ce durează prea mult timp pentru a lăsa cererea ta HTTP GET să aștepte. Deci, la prima cerere, cererea ta HTTP GET va fi redirecționată către acest URL:
https://s.wordpress.com/wp-content/plugins/mshots/default.gif
Și acel URL afișează această imagine:
Dar dacă aștepți un minut după prima cerere HTTP GET și repeți cererea, vei găsi captura de ecran. Cred că ceea ce vei dori să faci este să o apelezi pentru a o stoca în cache, să aștepți să o descarci și apoi să o stochezi local pe propriul tău server pentru a minimiza încărcarea pe serverele WordPress.com, astfel încât să nu se răzgândească să o ofere gratuit (sau, dacă va fi suficient trafic, ar putea chiar să o ofere ca serviciu plătit și poate să adauge și funcții API plătite!)
P.S. Apropo, pentru a demonstra că funcționează efectiv într-o pagină web, iată captura de ecran solicitată direct de la WordPress.com. Reține că poate fi diferită de captura de ecran pe care am salvat-o și am legat-o mai sus, sau dacă a trecut ceva timp de când cineva a vizualizat această pagină și cache-ul s-a șters, ar putea fi chiar imaginea "Generare previzualizare". Dacă da, așteaptă un minut și reîmprospătează pagina, ar trebui să apară:

Generatorul meu de postări video pentru blog (http://v.leau.co/) face acest lucru, dar nu în contextul WordPress.
Introduci o interogare, de exemplu "superman" (apoi aștepți (fără nicio indicație că se întâmplă ceva) (deoarece eu sunt singurul utilizator)), apoi selectezi videoclipurile pe care dorești să le postezi, apeși pe "generate code" și obții codul în care miniaturile sunt găzduite pe site-ul meu deoarece acestea au fost descărcate în timpul acesta. Acest cod poate fi copiat și lipit într-o postare.
Cu alte cuvinte, dacă ai pune codul într-o funcție, aceasta ar returna bucata de cod, de exemplu un link href către videoclip care este adăugat la conținut sau link-ul către imaginea reprezentativă care este descărcată local.
Este aceasta bucata de cod pe care o cauți? Cred că esențialul este:
O funcție pentru a prelua mai multe rezultate (pentru cazul în care vrei să afișezi mai multe videoclipuri în codul rezultat, nu doar unul specific):
function retrieveMoreResults($key, $q, $start, $cache) {
$url = "http://ajax.googleapis.com/ajax/services/search/video?v=1.0&q=" . $q . "&rsz=large&start=" . $start. "&key=" . $key;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_REFERER, $referer);
$body = curl_exec($ch);
curl_close($ch);
$responseData = json_decode($body, true);
$tempOutputString .= display($responseData, $cache, $q);
return $tempOutputString;
}
O funcție pentru a obține pagina inițială de rezultate:
function retrieveResults($key, $q, $cache) {
# primul apel
$url = "http://ajax.googleapis.com/ajax/services/search/video?v=1.0&q=" . $q . "&rsz=large&key=" . $key;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_REFERER, $referer);
$body = curl_exec($ch);
curl_close($ch);
$responseData = json_decode($body, true);
$tempOutputString = "";
$tempOutputString .= display($responseData, $cache, $q);
$boolFirstRequest = true;
foreach ($responseData["responseData"]["cursor"]["pages"] as $GsearchResultClass) {
$start = $GsearchResultClass["start"];
if ($boolFirstRequest) {
$boolFirstRequest = false;
} else {
$tempOutputString .= retrieveMoreResults($key, $q, $start, $cache);
}
}
return $tempOutputString;
}
O funcție pentru a afișa, descărca miniaturile într-un anumit director (variabilă) și pentru a returna o bucată de cod de inserat în postare:
function display($responseData, $cache, $tag) {
$strBuffer="";
foreach ($responseData["responseData"]["results"] as $GsearchResultClass) {
#
# există URL-uri de la YouTube și de la Google Video, acestea sunt diferite
# cel de la Google Video conține cuvântul "ThumbnailServer"
# exemplu:
# youtube: http://1.gvt0.com/vi/6jKzr143K8U/default.jpg
# video.google: http://3.gvt0.com/ThumbnailServer2?app=vss&contentid=7efbd69963e4cc67&offsetms=30000&itag=w160&hl=en&sigh=J6N1fv_It6H5jJWX51fKt-eYqNk
#
$thumbId="";
$imageThumb=$GsearchResultClass["tbUrl"];
if (strstr($imageThumb, 'ThumbnailServer')) {
$imgStringBits = explode('&',$imageThumb);
$parsedImgStr=strstr($imgStringBits[1],'=');
$parsedImgStr = substr($parsedImgStr,1);
$thumbId = $parsedImgStr;
} else {
$imgStringBits = explode('/',$imageThumb);
$thumbId = $imgStringBits[4];
}
$imgFile=$cache . "/" . $thumbId . ".jpg";
#
# Acum că avem numele fișierului imaginii, verificăm dacă îl avem deja în cache:
# - dacă îl avem, NU îl ștergem niciodată (de ce am face asta?)
# - dacă nu îl avem... îl obținem prin curl
#
if (!file_exists($imgFile)) {
$ch = curl_init ();
$timeout = 5;
curl_setopt ($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows; U; Windows NT 5.1; pl; rv:1.9) Gecko/2008052906 Firefox/3.0');
curl_setopt ($ch, CURLOPT_AUTOREFERER, true);
curl_setopt ($ch, CURLOPT_URL, $imageThumb);
curl_setopt ($ch, CURLOPT_HEADER, false);
curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt ($ch, CURLOPT_BINARYTRANSFER, true);
curl_setopt ($ch, CURLOPT_VERBOSE, 1);
$rawdata = curl_exec ($ch);
curl_close ($ch);
if($rawdata) {
$fp = fopen($imgFile, 'w');
fwrite($fp, $rawdata);
fclose($fp);
} else {
#
# Dacă acțiunea noastră cu curl nu returnează nimic, folosim imaginea implicită
#
$imgfile="images/default.jpg";
}
}
#
# Acum că avem URL-ul imaginii, creăm un div (hmm.. poate voi muta stilizarea
# ulterior într-un fișier CSS separat) care conține miniatura video, link
# și descrierea. Dacă dorești, poți adăuga toți ceilalți parametri
# returnați de Google, cum ar fi durata etc...
#
$strBuffer .= "<div style=\"float:left;width:125px;height:130px;font-size:8px;font-family:arial;\" class=\"thumb\"><div>";
$strBuffer .= "<a href=\"#\" class=\"del\" id=\"$thumbId\"> ADAUGĂ</a><br />";
$strBuffer .= "<a href=\"" . $GsearchResultClass["playUrl"] . "\" target=\"_blank\">";
$strBuffer .= "<img src=\"" . $imgFile . "\" alt=\"" . $GsearchResultClass["title"] . "\" border=\"0\" width=\"120\">";
$strBuffer .= "</a><br />\n";
#
# De asemenea, adăugăm o opțiune de ștergere, pentru moment aceasta doar elimină elementul din pagină
# dar în versiunea următoare ar trebui să facă un apel AJAX pentru a scrie ID-ul undeva
# astfel încât să nu-l mai vedem niciodată.
#
$strBuffer .= $GsearchResultClass["titleNoFormatting"] . "<br />";
$strBuffer .= "</div></div>\n";
}
return $strBuffer;
}
O funcție pentru a apela cele de mai sus:
function moviePage($tag, $cacheName, $cacheTime, $key) {
$cache = $cacheName . "/" . $tag;
checkCache($cache);
cleanCacheHTML($cache);
$filename = $tag . ".html";
$spFile=$cache . "/" . $filename;
if (file_exists($spFile) && filemtime($spFile) > $cacheTime ) {
$strBuffer = file_get_contents($spFile) . "<!-- " . $spFile . " din cache -->";
} else {
$strBuffer = retrieveResults($key, $tag, $cache);
}
$strBuffer .= "<br clear=\"all\">";
$fp = fopen($spFile, 'w');
fwrite($fp, $strBuffer);
fclose($fp);
return $strBuffer;
}
(cheia $key este cheia ta de API Google) (http://code.google.com/intl/ro-RO/more/)
În opinia mea, restul este doar "preluarea rezultatelor returnate și adăugarea lor în conținutul unei postări + setarea miniat

răspuns excelent! Ce zici dacă ai crea un câmp personalizat pentru ca utilizatorul să introducă URL-ul sursă al videoclipului și să execți descărcarea imaginii/legătura către imaginea locală la salvarea articolului? Un pas final ar fi ca atunci când actualizezi articolul cu un URL nou, imaginea veche să fie ștearsă și cea nouă să fie adăugată/legată. Dacă ai putea extinde codul cu această funcționalitate, cred că ar fi foarte util pentru cititori.

Nu sunt sigur dacă am înțeles exact ce vrei să spui, dar am găsit această soluție alternativă:
http://wpworks.wordpress.com/2010/12/23/display-youtube-thumbnail-with-wordpress-custom-field/
Cu stimă,

Funcție pentru a afișa imaginea pe baza URL-ului? Este acesta genul de lucru la care te-ai gândit?
function get_youtube_screen( $url = '', $type = 'default', $echo = true ) {
if( empty( $url ) )
return false;
if( !isset( $type ) )
$type = '';
$url = esc_url( $url );
preg_match("|[\\?&]v=([^&#]*)|",$url,$vid_id);
if( !isset( $vid_id[1] ) )
return false;
$img_server_num = 'i'. rand(1,4);
switch( $type ) {
case 'large':
$img = "<img src=\"http://{$img_server_num}.ytimg.com/vi/{$vid_id[1]}/0.jpg\" alt=\"Miniatură YouTube mare\" title=\"Miniatură YouTube mare\" />";
break;
case 'first':
// Miniatură a primului cadru
$img = "<img src=\"http://{$img_server_num}.ytimg.com/vi/{$vid_id[1]}/1.jpg\" alt=\"Prima miniatură YouTube\" title=\"Prima miniatură YouTube\" />";
break;
case 'small':
// Miniatură a unui cadru ulterior (nu sunt sigur cum determină acest lucru)
$img = "<img src=\"http://{$img_server_num}.ytimg.com/vi/{$vid_id[1]}/2.jpg\" alt=\"Miniatură YouTube mică\" title=\"Miniatură YouTube mică\" />";
break;
case 'default':
case '':
default:
$img = "<img src=\"http://{$img_server_num}.ytimg.com/vi/{$vid_id[1]}/default.jpg\" alt=\"Miniatură YouTube implicită\" title=\"Miniatură YouTube implicită\" />";
break;
}
if( $echo )
echo $img;
else
return $img;
}
// Exemple de apelare
get_youtube_screen( "http://www.youtube.com/watch?v=dZfmPREbTd8", 'default' );
get_youtube_screen( "http://www.youtube.com/watch?v=dZfmPREbTd8", 'large' );
get_youtube_screen( "http://www.youtube.com/watch?v=dZfmPREbTd8", 'small' );
get_youtube_screen( "http://www.youtube.com/watch?v=dZfmPREbTd8", 'first' );
YouTube pare să ofere imagini de la câteva servere pentru miniaturi..
iN.ytimg.com
Unde N este de obicei o valoare numerică de la 1-4 (uneori 5, dar nu a fost consistent în testare).
De asemenea, folosesc img.youtube.com
, dar mi-a plăcut ideea de a prelua de la servere alternative, așa că am codat funcția să aleagă aleatoriu unul dintre cele 4 servere pentru a afișa imaginea.
NOTĂ: Nu există întotdeauna o imagine pentru fiecare dimensiune pentru fiecare videoclip, unele vor apărea goale, dar imaginea implicită pare să funcționeze constant în URL-urile video pe care le-am testat.
Spune-mi dacă te ajută..

Răspuns frumos, +1. Aceasta a fost o întrebare grozavă; 4 răspunsuri complet diferite și toate aparent soluții foarte valide. Pur și simplu iubesc WA!

Am analizat clasa embed și filtrele disponibile, dar nu am putut găsi nicio modalitate ușoară de a transfera imaginea din obiectul embed (care de fapt conține URL-ul imaginii) către funcțiile shortcode care generează HTML-ul. Obiectul embed nu transmite în prezent (din câte am putut vedea) datele necesare către filtrele/hook-urile disponibile. Nu sunt sigur de ce clasa embed nu transmite informațiile despre imagine (pe care le are), ar avea sens să o facă..
