Mit WordPress 2.9 wurde die Möglichkeit eingeführt, Videos einer Vielzahl von Websites ohne grossen Aufwand einzubinden. Dazu muss man lediglich die URL eines Videos auf einer einzelnen Zeile einfügen, danach kann man ganz normal mit dem Schreiben fortfahren. Das Ganze funktioniert mit der sogenannten oEmbed Technik. Diese habe ich mir für die folgende Herausforderung zu Nutzen gemacht.

Vimeo

Vimeo

Anforderung

Für eine aktuelle Aufgabe suchte ich einen Weg, um einfach Vimeo Videos auf einem Blog zu veröffentlichen. Die Umsetzung erforderte einige Details, sodass rasch Custom Post Types eingesetzt wurden. Bei diesem Post Type gibt es dann eine Meta Box, bei welchem einfach die URL zum Video angegeben werden kann. Diese wird dann verwendet, um einerseits das Video auszugeben und andererseits auch direkt das Standbild des Videos als Post Thumbnail zu speichern.

oEmbed

oEmbed ist ein Format für die eingebettete Darstellung einer URL auf anderen Websites. Mit seiner simplen API können Websites eingebettete Inhalte wie Fotos und Videos einfügen, indem ein User bloss den Link dazu einfügen muss. Dazu definiert der Anbieter ein Muster, wie seine URLs aufgebaut sind, auf welches dann WordPress die URL untersuchen kann. Wird festgestellt, dass es eine gültige URL zu einem Vimeo Video ist, wird deren API aufgerufen.

Weitere Informationen zum Einfügen von Videos in WordPress gibt es im WordPress Codex. Es gibt auch eine Dokumentation der Vimeo oEmbed API.

Umsetzung

Bei der Umsetzung war ich darüber erstaunt, wie viele Zeilen Code es schlussendlich benötigte, um das Ganze zum Laufen zu bringen. Doch fangen wir einmal von vorne an. Zu Beginn habe ich ein neues Must-Use Plugin (PHP-Datei im mu-plugins Ordner) erstellt und dort folgenden Code eingefügt:

<?php
add_action( 'publish_video', 'wpm_publish_video' ); // 'publish_post' bei normalen Posts

/**
 * Diese Funktion wird beim Publizieren eines Posts aufgerufen,
 * damit wir ein das Post Thumbnail hinzufügen können
 *
 * @param int $post_id Die ID des Posts
 */
function wpm_publish_video( $post_id ) {
	global $wpdb; // Datenbank-Objekt laden

	// Reine Vorsichtsmassnahme
	if ( 'video' !== get_post_type( $post_id ) )
		return false;

	// Nur fortfahren, wenn eine URL angegeben wurde und es noch kein Post Thumbnail gibt
	if ( '' === get_post_meta( $post_id, '_thumbnail_id', true ) || '' === $video = get_post_meta( $post_id, '_vimeo_url', true ) )
		return false;

}
?>

Mit dieser Funktion klinken wir uns erst in den Publizierungs-Vorgang des Beitrags (in diesem Fall vom Post Type video) ein und laden das WordPress Datenbank-Objekt. Mit der zweiten If-Abfrage stellen wir sicher, dass noch kein Post Thumbnail gesetzt wurde und dass eine Video URL angegeben wurde.

Als nächsten Schritt kann man dann die Informationen zum Video von Vimeo laden. Mir reicht daher eine einfache Abfrage einer einzigen URL. Möchte man aber beispielsweise automatisch auch andere Provider wie YouTube unterstützen, sollte man sich die WP_oEmbed Klasse in der Datei wp-includes/class-oembed.php etwas genauer ansehen, da dort die regulären Ausdrücke und die nötigen Methoden beschrieben sind.

$url = "http://vimeo.com/api/oembed.json?url=$video";
// Video Infos laden
if ( ! $response = wp_remote_retrieve_body( wp_remote_get( $url ) ) )
	return false;

$json = json_decode( $response );
// JSON parsen
if ( null === $json )
	return false;

Dieser Abschnitt, der direkt nach der Prüfung des Post Thumbnails eingefügt wird, holt nun also die Informationen zu einem Video, mit wp_remote_body laden wir auch nur den Body und nicht noch die HTTP Header. Falls diese Funktion einen Fehler zurückgibt, beenden wir auch unsere Funktion, denn ohne Inhalt können wir ja nichts anfangen. Danach wandeln wir nur noch den JSON String in ein PHP Objekt um und fahren nur im Erfolgsfall fort.

Die Rückgabe der API sieht übrigens wie folgt aus (bei XML). Uns interessiert dabei das Feld thumbnail_url, wenn man möchte kann man aber auch noch über thumbnail_width und thumbnail_height die Bildmasse auslesen.

Vimeo oEmbed API Resultat (XML)

Das kriegen wir von Vimeo zurück

Jetzt muss man ja eigentlich nur noch das Bild laden und als Post Thumbnail speichern. Klingt zwar einfach, aber es war doch umfangreicher als ich zuerst gedacht habe. Ich habe das deshalb in eine zweite Funktion ausgelagert.

// Standbild URL und Titel des Videos auslesen
$thumbnail_url = $json->thumbnail_url;
$title = $json->title;
// *Magic*
$wp_thumb_id = wpm_generate_post_thumbnail( $post_id, $thumbnail_url, $title );
if ( ! $wp_thumb_id )
	return false;

// Thumbnail ID setzen
update_post_meta( $post_id, '_thumbnail_id', $wp_thumb_id );

In der neuen Funktion wpm_generate_post_thumbnail müssen wir nun das Bild aufrufen und unter dem richtigen Dateinamen in WordPress hochladen, wofür es praktischerweise die Hilfsfunktion wp_upload_bits gibt. Danach muss dann das Standbild als Attachment eingetragen werden, was jedoch auch ein paar Kniffe benötigt.

/**
 * Post Thumbnail hinzufügen von einer bestimmten URL
 */
function wpm_generate_post_thumbnail( $post_id, $url, $title = '' ) {
	if ( ! $response = wp_remote_retrieve_body( wp_remote_get( $url ) ) )
		return false;

	// Dateinamen herausfiltern
	$filename = substr( $url, ( strrpos( $url, '/' ) ) +1 );

	// Datei in WordPress hochladen
	$upload = wp_upload_bits( $filename, null, $response );
	if ( false !== $upload['error'] )
		return false;

	// MIME Type überprüfen, zurückgeben
	$filetype = wp_check_filetype( $filename );

	// Informationen zum Attachment
	$attachment = array(
		'post_mime_type' => $filetype['type'],
		'guid' => $upload['url'],
		'post_title' => $title,
		'post_content' => '', // z.B. Video Beschreibung
	);
	// Attachment einfügen
	$thumb_id = wp_insert_attachment( $attachment, $upload['file'], $post_id );
	if ( is_wp_error( $thumb_id ) )
		return false;

	// Für die Verknüpfung mit dem Beitrag müssen wir diese Klasse laden
	require_once(ABSPATH . '/wp-admin/includes/image.php');
	// Attachment mit Post verknüpfen
	wp_update_attachment_metadata( $thumb_id, wp_generate_attachment_metadata( $thumb_id, $upload['file'] ) );
	return $thumb_id;
}

Mit diesen zwei Funktionen kann man nun ein Custom Field auslesen, die nötigen Informationen zum Video laden und das Standbild schliesslich als Post Thumbnail verwenden. Dies alles mit nur einem Mausklick beim Veröffentlichen des Artikels. Und das Beste daran: Funktioniert es einmal nicht oder das Standbild wurde geändert, kann man das vorhandene Thumbnail entfernen und einfach den Beitrag nochmals speichern.

Ich habe den Code einfach so aus dem Plugin kopiert, falls es also nicht funktioniert, einfach sagen. Bestimmt kann man das Ganze auch vereinfachen, bin also für jeden Ratschlag dankbar.

Nachtrag: Selbstverständlich dürft ihr auch noch sehen, wie das Ganze dann im Backend aussieht. Nichts Spezielles, ich habe zum Testen mal ein Video von Marcel Widmer genommen.

Thumbnail via oEmbed Thumbnail

Thumbnail via oEmbed Thumbnail