<?php if (!defined('PmWiki')) exit(); /** \file video5.php \brief HTML5 Video Support for PmWiki This recipe provides the HTML5 <video> tag for PmWiki. Copyright 2012, 2013, 2015, 2022 Tom Gem <tomgem@me.com>, an adaptation of HTML5video.php by GNUZoo, copyright 2007, 2010 GNUZoo <guru@gnuzoo.org> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Full documentation: http://www.pmwiki.org/wiki/Cookbook/Video5 Version history: 2012-11-01 - initial release 2013-10-22 - added support for the track element (subtitles) - removed necessity to use the (:video file:) markup without file extensions - video format order is now configurable - video5 now shows upload links if no video files are found - added php5.2 as a requirement on the recipe page 2013-10-23 - added support for the srt track format 2013-12-03 - added support for attachments on other groups/pages (:video group/page/file:) 2015-10-05 - added support for php 5.5 (replaced Markup with Markup_e) 2022-10-28 - update for PHP 8 (Petko Yotov pmwiki.org/petko) 2022-10-30 - replaced all tabs with spaces */ // recipe version $RecipeInfo['Video5']['Version'] = '2022-10-30'; // get and set defaults SDV($VideoWidth, '640'); // default video width is 640 (480i 4:3) SDV($VideoHeight, '480'); // default video height is 480 (480i 4:3) SDV($VideoPreload, 'auto'); // default is to load video when page loads (auto|metadata|none) SDV($VideoAutoplay, 0); // default is not to autoplay video (0|1) SDV($VideoControls, 1); // default is a player with controls (0|1) SDV($VideoLoop, 0); // default is not to loop video (0|1) SDV($VideoMuted, 0); // default is not to mute audio (0|1) SDVA($VideoExtensions, array('mp4','ogv','webm')); // default video format order SDVA($PosterExtensions, array('gif','jpg','png')); // default poster format order (reverse order) SDVA($TrackExtensions, array('srt','vtt')); // default track format order (reverse order) // text which will be shown in old browsers instead of video SDV($VideoNotSupportedText, 'Sorry, your browser does not support HTML5 video.'); // use this if your videos are not stored as 'attachments' of your wiki pages // example setting for config.php (note the trailing slash): // $VideoUrl = 'http://server.example.com/path/to/videofolder/'; SDV($VideoUrl, 0); // get the currently active language. only used by the track (subtitles) element if (isset($XLLangs['0'])) { $VideoLang = $XLLangs['0']; } else { $VideoLang = 'en'; } // video markup definition Markup('Video5', 'fulltext', '/\\(:(video)(\\s.*?)?:\\)/i', "mu_Video5"); function mu_Video5($m) { return Video5($m[1],$m[2]); } // main (and only) function function Video5($name, $args) { // those are needed here global $pagename, $PageUrl, $UploadDir, $UploadPrefixFmt, $UploadUrlFmt, $EnableDirectDownload, $VideoWidth, $VideoHeight, $VideoAutoplay, $VideoControls, $VideoLoop, $VideoMuted, $VideoPreload, $VideoExtensions, $PosterExtensions, $TrackExtensions, $VideoNotSupportedText, $VideoLang, $VideoUrl; // a little helper $nl = "\n"; // parse arguments $args = ParseArgs($args); // get video file basename and dirname $VideoFile = pathinfo($args[''][0], PATHINFO_FILENAME); $VideoDirName = pathinfo($args[''][0], PATHINFO_DIRNAME); // get the path to the upload dir if ($VideoDirName == ".") { // the attachment can be found on the same group/page $VideoDir = FmtPageName($UploadDir.$UploadPrefixFmt, $pagename); } else { // the attachment can be found on another group/page $VideoDirUnix = str_replace('.', '/', $VideoDirName); $VideoDir = $UploadDir.'/'.$VideoDirUnix; } // get video src url $VideoAttached = 0; if (empty($VideoUrl)) { // respect setting of $EnableDirectDownload // please note, video playback does not work with most browsers if $EnableDirectDownload=0; is set if (IsEnabled($EnableDirectDownload, 1)) { if ($VideoDirName == ".") { // the attachment can be found on the same group/page $VideoUrl = FmtPageName($UploadUrlFmt.$UploadPrefixFmt.'/', $pagename); } else { // the attachment can be found on another group/page $VideoUrl = $UploadUrlFmt.'/'.$VideoDirUnix.'/'; } } else { // note, attachments on other groups/pages will not work if $EnableDirectDownload=0 is set $VideoUrl = FmtPageName('$PageUrl?action=download&upname=', $pagename); } $VideoAttached = 1; } // assemble complete video source url $VideoSrc = $VideoUrl.$VideoFile; // get and set video resolution if (isset($args['width'])) { $VideoWidth = $args['width']; } if (isset($args['height'])) { $VideoHeight = $args['height']; } // start gathering video options $VideoOpt = ' width="'.$VideoWidth.'" height="'.$VideoHeight.'" '; // get and set preload behaviour if (isset($args['preload'])) { $VideoPreload = $args['preload']; } $VideoOpt = $VideoOpt.'preload="'.$VideoPreload.'" '; // get and set boolean video attributes if (isset($args['autoplay'])) { if (!empty($args['autoplay'])) { $VideoOpt = $VideoOpt.'autoplay="autoplay" '; } } else { if (!empty($VideoAutoplay)) { $VideoOpt = $VideoOpt.'autoplay="autoplay" '; } } if (isset($args['controls'])) { if (!empty($args['controls'])) { $VideoOpt = $VideoOpt.'controls="controls" '; } } else { if (!empty($VideoControls)) { $VideoOpt = $VideoOpt.'controls="controls" '; } } if (isset($args['loop'])) { if (!empty($args['loop'])) { $VideoOpt = $VideoOpt.'loop="loop" '; } } else { if (!empty($VideoLoop)) { $VideoOpt = $VideoOpt.'loop="loop" '; } } if (isset($args['muted'])) { if (!empty($args['muted'])) { $VideoOpt = $VideoOpt.'muted="muted" '; } } else { if (!empty($VideoMuted)) { $VideoOpt = $VideoOpt.'muted="muted" '; } } // search for existing video files and add them to the <video> tag if they do $Videos = ''; $VideoFound = 0; foreach ($VideoExtensions as $Extension) { $VideoPath = $VideoDir.'/'.$VideoFile.'.'.$Extension; // can't check if videos exist if $VideoUrl was set manually - if so, just add them all if (file_exists($VideoPath) || empty($VideoAttached)) { if ($Extension == 'ogv') { $VideoType = 'type="video/ogg"'; } else { $VideoType = 'type="video/'.$Extension.'"'; } $Videos = $Videos.'<source src="'.$VideoSrc.'.'.$Extension.'" '.$VideoType.' />'.$nl; $VideoFound = 1; } } // search for existing poster files and add the last match to the <video> tag $PosterAttribute = ''; $PosterImg = ''; foreach ($PosterExtensions as $Extension) { $PosterPath = $VideoDir.'/'.$VideoFile.'.'.$Extension; // can't check if a poster file exists if $VideoUrl was set manually - if so, just add it if (file_exists($PosterPath) || empty($VideoAttached)) { $PosterSrc = $VideoSrc.'.'.$Extension; $PosterAttribute = 'poster="'.$PosterSrc.'"'; $PosterImg = '<img src="'.$PosterSrc.'" width="'.$VideoWidth.'" height="'.$VideoHeight.'" alt="'.$VideoFile.'" />'; } } // search for existing track files (subtitles) and add the last match to the <video> tag $TrackAttribute = ''; $TrackFile = ''; foreach ($TrackExtensions as $Extension) { $TrackPath = $VideoDir.'/'.$VideoFile.'.'.$Extension; // can't check if a track file exists if $VideoUrl was set manually - if so, just add it if (file_exists($TrackPath) || empty($VideoAttached)) { $TrackSrc = $VideoSrc.'.'.$Extension; $TrackAttribute = 'poster="'.$TrackSrc.'"'; $TrackFile = '<track src="'.$TrackSrc.'" kind="subtitles" srclang="'.$VideoLang.'" label="'.$VideoFile.'" default />'; } } // generate and return html for the wiki page if ($VideoFound == 1) { return Keep('<video'.$VideoOpt.$PosterAttribute.'>'.$nl.$Videos.$PosterImg.$nl.$TrackFile.$nl.'<p class="novideo">'.$VideoNotSupportedText.'</p>'.$nl.'</video>'); } else { // show upload links if no video files can be found $VideoUpload = ''; $VideoUploadlink = FmtPageName('$PageUrl?action=upload&upname=', $pagename); foreach ($VideoExtensions as $Extension) { $VideoUpload = $VideoUpload.'<a rel="nofollow" class="createlinktext" href="'.$VideoUploadlink.$VideoFile.'.'.$Extension.'">'.$VideoFile.'.'.$Extension.'</a>'; $VideoUpload = $VideoUpload.'<a rel="nofollow" class="createlink" href="'.$VideoUploadlink.$VideoFile.'.'.$Extension.'"> Δ </a>'; } return Keep('<p class="novideo">No video files ('.$VideoUpload.') found.</p>'); } }