
Guido Schmechel
TYPO3 Developer

Einen eigenen TYPO3 MediaRenderer schreiben
Seit Version TYPO3 v7 kann man eigene MediaRenderer registrieren. In dem damaligen Beispiel wurde noch MyVideo als Beispiel genutzt. Na, wer kennt es noch? Für das Tutorial hab ich mir tiktok als Beispiel geschnappt. Die fertige Extension könnt ihr hier finden. Mit dem MediaRenderer hängen wir uns in den Core und sind somit stabil und Updates sind kein Problem.
Bevor wir mit der Programmierung startet, überlegt euch einen Key. Diese wird als Dateiendung genutzt und auch an den entsprechenden Stellen so angezeigt. Beispiel: Videoname.tiktok oder eben video/tiktok.
ext_localconf.php
defined('TYPO3_MODE') || die();
(function ($mediaFileExt) {
$GLOBALS['TYPO3_CONF_VARS']['SYS']['fal']['onlineMediaHelpers'][$mediaFileExt] = \Ayacoo\Tiktok\Helper\TiktokHelper::class;
$rendererRegistry = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Resource\Rendering\RendererRegistry::class);
$rendererRegistry->registerRendererClass(\Ayacoo\Tiktok\Rendering\TiktokRenderer::class);
$GLOBALS['TYPO3_CONF_VARS']['SYS']['FileInfo']['fileExtensionToMimeType'][$mediaFileExt] = 'video/tiktok';
$GLOBALS['TYPO3_CONF_VARS']['SYS']['mediafile_ext'] .= ',' . $mediaFileExt;
$iconRegistry = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Imaging\IconRegistry::class);
$iconRegistry->registerIcon(
'mimetypes-media-image-tiktok',
\TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider::class,
['source' => 'EXT:tiktok/Resources/Public/Icons/tiktok.svg']
);
$iconRegistry->registerFileExtension('tiktok', 'mimetypes-media-image-tiktok');
})('tiktok');
Was passiert hier? Wir definieren zuerst einen Helper. Diese Klasse wird vom
Core aufgerufen um den Dateidownload bzw. die Verarbeitung durchzuführen.
Wir holen uns also z.B. aus der oEmbed Schnittstelle alle benötigten Daten.
Der Renderer ist letztlich für das Ausspiele der Daten da. Im Falle von
tiktok ist es lediglich das Holen des zwischengespeicherten HTML.
Und zu guter Letzt registrieren wir noch ein Icon für diesen Dateitypen.
Hinweis: Ab v11 kann man die Icons übrigens moderner registrieren, siehe TYPO3
Documentation.
MediaHelper
Der MediaHelper erbt vom AbstractOEmbedHelper. Damit einher gehen ein paar
notwendige Funktionen. Mit der Funktion transformUrlToFile habt ihr die
Möglichkeit das erlaubte URL Format zu steuern. Bei tiktok ist der regex
relativ simpel. Komplizierter ist es bei Youtube und Vimeo, weil es mehrere
Varianten gibt.
In der Funktion transformMediaIdToFile wird letztlich die Datei in fileadmin
oder anderem beliebigen Storage abgespeichert. Hier nutzt man in der Regel
den title des Videos aus dem oEmbed Request.
Die Funktion getPublicUrl ist besonders für das Frontend interessant, was in
unserem Falle letztlich den Link zur Tiktok Detailseite generiert.
Bei der Funktion getPreviewImage sind wir dafür verantwortlich das Thumbnail
zum Video zu holen. Bei tiktok gibt es einen URL Pfad im oEmbed Request, den
wir bereits in der Datenbank zwischengespeichert haben. Die Speichermethode
selbst kann dann bequem vom Core übernommen werden.
Die Funktion getMetaData bereitet die Daten auf, die dann letztlich in
sys_file_metadata landet. So könnt ihr weitere Informationen speichern, die
euch die Anbieter mitgeben. Im Falle von Tiktok wird z.B. das komplett HTML
mitgeliefert, was wir damit abspeichern. Das würde normalerweise erst im
Renderer gebaut werden.
public function transformUrlToFile($url, Folder $targetFolder)
{
$videoId = null;
// Try to get the Tiktok code from given url.
// - https://www.tiktok.com/@username/video/code?parameter # Share URL
if (preg_match('%(?:.*)tiktok\.com\/@(?:[a-z.\-_0-9]*)\/video\/([0-9]*)%i', $url, $match)) {
$videoId = $match[1];
}
if (empty($videoId)) {
return null;
}
return $this->transformMediaIdToFile($videoId, $targetFolder, $this->extension);
}
protected function transformMediaIdToFile($mediaId, Folder $targetFolder, $fileExtension)
{
$file = $this->findExistingFileByOnlineMediaId($mediaId, $targetFolder, $fileExtension);
if ($file === null) {
$fileName = $mediaId . '.' . $fileExtension;
$oEmbed = $this->getOEmbedData($mediaId);
if (!empty($oEmbed['title'])) {
$title = $this->handleTiktokTitle($oEmbed['title']);
if (!empty($title)) {
$fileName = $title . '.' . $fileExtension;
}
}
$file = $this->createNewFile($targetFolder, $fileName, $mediaId);
}
return $file;
}
public function getPublicUrl(File $file, $relativeToCurrentScript = false)
{
// @deprecated $relativeToCurrentScript since v11, will be removed in TYPO3 v12.0
$videoId = $this->getOnlineMediaId($file);
$properties = $file->getProperties();
$username = $properties['tiktok_username'] ?? '';
return sprintf(self::TIKTOK_URL . '@' . $username . '/video/%s', rawurlencode($videoId));
}
public function getPreviewImage(File $file)
{
$properties = $file->getProperties();
$previewImageUrl = $properties['tiktok_thumbnail'] ?? '';
$videoId = $this->getOnlineMediaId($file);
$temporaryFileName = $this->getTempFolderPath() . 'tiktok_' . md5($videoId) . '.jpg';
if (!empty($previewImageUrl)) {
$previewImage = GeneralUtility::getUrl($previewImageUrl);
file_put_contents($temporaryFileName, $previewImage);
GeneralUtility::fixPermissions($temporaryFileName);
return $temporaryFileName;
}
return '';
}
public function getMetaData(File $file)
{
$metaData = [];
$oEmbed = $this->getOEmbedData($this->getOnlineMediaId($file));
if ($oEmbed) {
$metaData['width'] = (int)$oEmbed['width'];
$metaData['height'] = (int)$oEmbed['height'];
if (empty($file->getProperty('title'))) {
$metaData['title'] = $this->handleTiktokTitle($oEmbed['title']);
}
$metaData['author'] = $oEmbed['author_name'];
$metaData['tiktok_html'] = preg_replace(self::UNICODE_PATTERN, '', $oEmbed['html']);
$metaData['tiktok_thumbnail'] = $oEmbed['thumbnail_url'];
$metaData['tiktok_author_url'] = $oEmbed['author_url'];
$metaData['tiktok_username'] = str_replace(self::TIKTOK_URL . '@', '', $oEmbed['author_url']);
}
return $metaData;
}
MediaRenderer
Der Renderer ist recht klein gehalten. Neben einer MimeType Prüfung findet hier der Aufbau des HTMLs statt. Beim YoutubeRenderer sieht man ganz gut, was noch alles geht. Neben dem Erzeugen des HTML werden auch alle möglichen Optionen überprüft, die man z.B. via Fluid übermitteln kann. Beispiel: Man möchte autoplay einschalten. Bei tiktok ist das relativ einfach, weil es selbst schon angeboten wird.
public function render(FileInterface $file, $width, $height, array $options = [], $usedPathsRelativeToCurrentScript = false)
{
return $file->getProperty('tiktok_html') ?? '';
}
So sieht es im Backend aus



Fazit
Der MediaRenderer ist ein unterschätztes Feature von TYPO3 und sicher auch nicht allen bekannt. Seit Version 7 kann man sich in den TYPO3 Core hängen und stabil weitere Anbieter ergänzen, wie z.B. Tiktok oder Instagram. Und wer selbst das Ganze mal ausprobieren möchte: Die ARD Mediathek bietet in Teilen auch eine Einbettung an.