Recuperare automaticamente l'immagine di YouTube per la miniatura?

27 nov 2010, 05:01:31
Visualizzazioni: 8.77K
Voti: 6

Ho un tipo di post personalizzato che accetta un frammento HTML di embed di YouTube, un titolo e un'immagine in evidenza. Attualmente, devo cercare manualmente un'immagine per l'immagine in evidenza, ma idealmente vorrei poter scaricare e ridimensionare automaticamente il primo fotogramma del video stesso basandomi sull'URL del video durante il processo di salvataggio del post. Se fatto correttamente, il mio tipo di post potrebbe richiedere solo il link e ottenere sia l'immagine che il codice di embed da quello.

Ad esempio, se il link del video è http://www.youtube.com/watch?v=2Jnpi-uBiIg il valore di v verrebbe estratto e utilizzato per scaricare l'immagine all'indirizzo http://img.youtube.com/vi/2Jnpi-uBiIg/0.jpg.

Sono molto nuovo nello sviluppo di WordPress, ma qualcosa mi dice che dovrei guardare agli hook (se li ho capiti correttamente).

3
Commenti

Proverei a usare e estendere oEmbed per questo, invece di un frammento HTML... Ma dopo aver passato un po' di tempo a esaminare quel codice nel core - questo consiglio a una persona nuova con WP sembra quasi come lanciarlo sotto un autobus. :)

Rarst Rarst
27 nov 2010 15:38:42

Sono solo molto curioso di sapere se la mia versione ha funzionato per te..?

MikeSchinkel MikeSchinkel
24 dic 2010 15:10:44

@Mike Periodo impegnativo dell'anno - dovrò tornarci sopra :) Ti ringrazio per le informazioni e riprenderò presto questo post per rileggere tutte le soluzioni nel prossimo futuro.

Sampson Sampson
24 dic 2010 18:46:38
Tutte le risposte alla domanda 4
1

Ciao @Jonathan Sampson:

Anche se non è esattamente quello che hai chiesto, potrebbe essere una soluzione valida e gratuita grazie a WordPress.com, come menzionato da @yoast in un tweet stamattina, riferendosi a questo articolo:

In pratica, puoi utilizzare il generatore di screenshot di WordPress.com con un URL in questo formato (che, secondo il blog post, Matt sembra aver approvato per un uso gratuito):

  • https://s.wordpress.com/mshots/v1/{URL-codificato}?w={larghezza}

Prendendo il tuo URL di esempio:

E codificandolo per l'uso con il generatore di screenshot, ottieni un URL simile a questo (per una larghezza di 400px):

https://s.wordpress.com/mshots/v1/http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3D2Jnpi-uBiIg?w=400

Ecco come appare lo screenshot (ho copiato l'immagine per conservarla, quindi non cambierà anche se il servizio WordPress viene modificato, invece di includere un link diretto al servizio per visualizzare l'immagine.) Non sono sicuro del perché abbia catturato solo il video e non l'intera pagina, ma il video è ancora meglio per quello che ti serve:

Screenshot di un video di YouTube catturato dal servizio di screenshot di WordPress
(fonte: mikeschinkel.com)

Ovviamente, la prima volta che fai una richiesta HTTP GET all'URL, non otterrai lo screenshot perché i server di WordPress.com devono prima acquisire l'immagine, il che richiede troppo tempo per far attendere la tua richiesta. Quindi, alla prima richiesta, verrai reindirizzato a questo URL:

  • https://s.wordpress.com/wp-content/plugins/mshots/default.gif

E questo URL mostra questa immagine:

Anteprima in generazione da WordPress.com

Ma se attendi un minuto dopo la prima richiesta e la ripeti, otterrai lo screenshot. Penso che quello che vorrai fare sia richiamarlo per memorizzarlo nella cache, attendere il download e poi conservarlo localmente sul tuo server per ridurre il carico sui server di WordPress.com, evitando che decidano di limitare questo servizio gratuito (o addirittura, se il traffico è sufficiente, potrebbero renderlo a pagamento con funzionalità API aggiuntive!)

P.S. A proposito, per dimostrare che funziona davvero in una pagina web, ecco lo screenshot richiesto direttamente da WordPress.com. Nota che potrebbe essere diverso dall'immagine che ho salvato e linkato sopra, oppure, se è passato molto tempo dall'ultima visualizzazione di questa pagina e la loro cache è stata cancellata, potrebbe mostrare l'immagine "Generating Preview". In tal caso, aspetta un minuto e aggiorna la pagina per visualizzare lo screenshot:

Screenshot di un video di YouTube direttamente dal servizio di screenshot di WordPress.com

23 dic 2010 14:13:48
Commenti

Sembra utile.. :)

t31os t31os
23 dic 2010 16:06:22
2

Il mio generatore di post per video blog (http://v.leau.co/) fa questo ma non in contesto WordPress.

Fornisci una query ad esempio "superman" (poi aspetti (senza alcuna notifica che sta facendo qualcosa) (dato che sono l'unico utente)), poi clicchi i video che vuoi postare, clicchi su genera codice e ottieni il codice dove le miniature sono ospitate sul mio sito perché nel frattempo le ha scaricate. Questo codice può essere copiato e incollato in un post.

In altre parole, se mettessi il codice in una funzione restituirebbe il pezzo di codice ad esempio un tag a con un link al video che viene aggiunto al contenuto oppure ad esempio il link all'immagine in evidenza che viene scaricata localmente.

È questo il codice che stai cercando? Penso che il nucleo sia:

Una funzione per recuperare più risultati (quindi se vuoi visualizzare più di 1 video nel codice risultante invece di 1 specifico):

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;
}

Una funzione per ottenere la pagina iniziale dei risultati:

function retrieveResults($key, $q, $cache) {    
# prima chiamata
$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;
}

Una funzione per visualizzare e scaricare le miniature in una certa directory (variabile) e per restituire un pezzo di codice da inserire nel post:

function display($responseData, $cache, $tag) {
$strBuffer="";

foreach ($responseData["responseData"]["results"] as $GsearchResultClass) {

    #
    # ci sono URL di YouTube e anche URL di Google Video, sono entrambi diversi
    # quello di Google video contiene la parola "ThumbnailServer"
    # esempio:
    # 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";

    #
    # Ora che abbiamo il nome del file immagine controlliamo se già esiste nella cache:
    # - se esiste NON cancellarlo mai (perché dovremmo?)
    # - se non esiste... beh, recuperiamolo via 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 {
            #
            # Se la nostra azione Curl non recupera nulla allora usa l'immagine predefinita
            #
            $imgfile="images/default.jpg";
        }
    }

    #
    # Ora che abbiamo l'URL dell'immagine creiamo un div (hmm.. potremmo spostare lo
    # stile successivamente in un CSS separato) contenente la miniatura del video, il link
    # e la descrizione. Se ti piace puoi aggiungere tutti gli altri
    # parametri che Google restituisce come durata ecc...
    #
    $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\"> AGGIUNGI</a><br />";                
    $strBuffer .=  "<a href=\"" .  $GsearchResultClass["playUrl"]  .    "\" target=\"_blank\">";
    $strBuffer .=  "<img src=\"" . $imgFile . "\" alt=\"" . $GsearchResultClass["title"] . "\" border=\"0\" width=\"120\">";
    $strBuffer .=  "</a><br />\n";
    #
    # Nota che aggiungiamo anche un'opzione per eliminare, per ora rimuove solo dalla pagina
    # ma nella prossima versione dovrebbe fare una chiamata AJAX per scrivere l'ID da qualche parte
    # così che non lo vedremo più.
    #
    $strBuffer .= $GsearchResultClass["titleNoFormatting"] . "<br />";
    $strBuffer .= "</div></div>\n";
}
return $strBuffer;
}

Una funzione per chiamare le precedenti:

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 . " from cache -->";
} else {                    
    $strBuffer = retrieveResults($key, $tag, $cache);
}
$strBuffer .=  "<br clear=\"all\">";
$fp = fopen($spFile, 'w');
fwrite($fp, $strBuffer);
fclose($fp);

return $strBuffer;  
}

(la $key è la tua chiave API di Google) (http://code.google.com/intl/it-IT/more/)

IMHO penso che il resto sia più che altro "prendere il codice restituito e aggiungerlo al contenuto di un post + impostare la miniatura scaricata nella cache come immagine in evidenza?

P.S. IMHO è sempre meglio postare una miniatura in un video quando si fa riferimento a video di YouTube poiché spesso i video più vecchi vengono rimossi da YouTube e lasciano brutti post come risultato. Con le tue miniature almeno l'immagine rimane lì per sempre così che in seguito hai un'idea di cosa avevi postato originariamente.

28 nov 2010 17:30:03
Commenti

ottima risposta! E se creassi un campo personalizzato per permettere all'utente di inserire l'URL sorgente del video e facessi eseguire il download dell'immagine/collegamento all'immagine locale al momento del salvataggio del post? Un ultimo passo sarebbe che quando aggiorni il post con un nuovo URL, la vecchia immagine viene eliminata e quella nuova viene aggiunta/collegata. Se potessi estendere il tuo codice con questa funzionalità penso che sarebbe molto utile per i lettori.

NetConstructor.com NetConstructor.com
29 nov 2010 19:53:59

sì... ma sono troppo impegnato lol, tra 2 settimane sono in vacanza...

edelwater edelwater
29 nov 2010 22:43:59
1

Non sono sicuro di aver capito esattamente cosa intendi, ma ho trovato questa soluzione alternativa:

http://wpworks.wordpress.com/2010/12/23/display-youtube-thumbnail-with-wordpress-custom-field/

Saluti

23 dic 2010 13:34:33
Commenti

@Alvaro Neto - È davvero piuttosto interessante, e non era una cosa che conoscevo. Peccato che con quel metodo sembrano disponibili solo piccole miniature.

MikeSchinkel MikeSchinkel
23 dic 2010 14:53:21
2

Funzione per visualizzare l'immagine basata sull'URL? È questo il tipo di cosa che avevi in mente?

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=\"Anteprima grande del video YouTube\" title=\"Anteprima video YouTube\" />";
            break;
        case 'first':
            // Anteprima del primo frame
            $img = "<img src=\"http://{$img_server_num}.ytimg.com/vi/{$vid_id[1]}/1.jpg\" alt=\"Primo frame del video YouTube\" title=\"Primo frame video YouTube\" />";
            break;
        case 'small':
            // Anteprima di un frame successivo (non sono sicuro di come determinino quale)
            $img = "<img src=\"http://{$img_server_num}.ytimg.com/vi/{$vid_id[1]}/2.jpg\" alt=\"Anteprima piccola del video YouTube\" title=\"Anteprima piccola video YouTube\" />";
            break;
        case 'default':
        case '':
        default:
            $img = "<img src=\"http://{$img_server_num}.ytimg.com/vi/{$vid_id[1]}/default.jpg\" alt=\"Anteprima predefinita del video YouTube\" title=\"Anteprima video YouTube\" />";
            break;
    }
    if( $echo )
        echo $img;
    else
        return $img;

}
// Esempi di chiamata

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 sembra servire le immagini da alcuni server per le miniature..

iN.ytimg.com

Dove N è solitamente un valore numerico da 1 a 4 (a volte 5, ma non era coerente nei test).

Usano anche img.youtube.com ma mi piaceva l'idea di recuperare da server alternativi, quindi ho codificato la funzione per scegliere casualmente uno tra 4 server da cui visualizzare l'immagine.

NOTA: Non c'è sempre un'immagine per ogni dimensione per ogni video, alcune potrebbero essere vuote, tuttavia l'immagine predefinita sembra funzionare costantemente negli URL video che ho testato.

Fammi sapere se questo ti aiuta..

23 dic 2010 19:04:53
Commenti

Ottima risposta, +1. Questa era una domanda fantastica; 4 risposte completamente diverse e tutte apparentemente soluzioni molto valide. Adoro WA!

MikeSchinkel MikeSchinkel
24 dic 2010 15:19:14

Ho esaminato la classe embed e i filtri disponibili, ma non ho trovato un modo semplice per trasportare l'immagine dall'oggetto embed (che in realtà contiene l'URL dell'immagine) alle funzioni degli shortcode che generano l'HTML, l'oggetto embed attualmente (per quanto ho potuto vedere) non passa i dati necessari ai filtri/hook disponibili. Non sono sicuro del perché la classe embed non trasmetta le informazioni sull'immagine (che possiede), avrebbe senso farlo...

t31os t31os
27 dic 2010 14:43:35