WordPress Random Video Backgrounds

Facebooktwitterredditpinterestlinkedinmail
2015-03-01-extreme-poster
Extreme

Have you ever thought about how to create random video backgrounds in WordPress?  Well me too!

Especially since I started playing with the GP Premium Elements Header blocks from GeneratePress.  This block can be purchased as part of the GP Premium Package from GeneratePress.  Click on the link to read about the wonderful capabilities of this paid plugin.  However, once you start using it, you realize that there is no setting to randomize the video on page load.  After contacting the Developer of GeneratePress, I realized there was no hook or easy way to do that.  BUMMER!  So I had to “roll-my-own” code.  DOABLE!

I have a working example on my About page.  If you reload the page you will get a random video, of 16 possible videos, delivered from the Server. My hosting environment at SiteGround has a built-in caching system on the Server which is generally refreshed every four hours, so on some devices and browsers the actual randomness of the first video is affected by that server caching mechanism.  Also, as you stay on that page, JavaScript will continuously randomly select one of the 16 possible videos.  The possibility of getting the same two in a row happens, but not often.  Random is random – just saying!

I first tackled the project with JavaScript thinking that would be the ideal solution.  I created a Plugin and enqueued the JavaScript file.  However, after the DOM loaded, there was a moment when the video poster (Page Header > Image) for the video selected with GP Premium Elements Header plugin was still visible.  I realized I needed to write PHP code in order to provide the optimum User Experience.

The main secret of both sets of code is the use of a multidimensional array for each.  If you set the multidimensional array to use a number as the outer array index, the inner array becomes addressable.  Once your code generates the random number then you can return data from the inner array like: videos[12][0].  The first number represents the random number returned, and the second number represents the video source URL from the inner array.  You retrieve the poster source URL by using videos[12][1]  It is sort of like a spreadsheet where the first number is the row number and the second number is the column number.  Remember that arrays are always ZERO based, meaning they start with the number zero, not the number one.  In our analogy, that means both the rows and columns start with the number zero.  To make life easier, in the PHP code, I have changed the inner array to an Associative Array, with named keys and value pairs.

Okay, enough explanation for now, let’s see some code!

define( 'MDWSC_VERSION', '0.0.23' );
add_action( 'init', 'mdwsc_init' );

function mdwsc_init() {
  include( plugin_dir_path( __FILE__ ) . 'admin/mdwsc-admin.php' );
  wp_register_script( 'mdwsc-full', plugins_url( 'js/mdwsc_full.js', __FILE__ ), array( 'jquery' ), MDWSC_VERSION, true );
  add_action( 'wp_enqueue_scripts', 'mdwsc_enqueue_scripts' );
  add_action('wp_head', 'buffer_start_mdwsc');
  add_action('wp_footer', 'buffer_end_mdwsc');
}

function mdwsc_enqueue_scripts() {
  wp_enqueue_script( 'mdwsc-full', plugins_url( 'js/mdwsc_full.js', __FILE__ ), array( 'jquery' ), MDWSC_VERSION, true );
}

The two most significant pieces of code above are Line #8 and Line #9.  In Line #8 we add a callback to the hook wp_head and the callback starts a buffer.  In Line #9 we add a callback to the hook wp_footer and the callback closes and flushes that buffer.  More about those two callbacks in the code below.

Here is the code from mdwsc-admin.php:

function callback_for_buffer_start_mdwsc( $buffer ) {
	// modify buffer here, and then return the updated code
	if ( is_front_page() ) {

	}

	if ( is_page( 'about' ) ) {
		$random    = get_random_videos_mdwsc();
		$vidsrc    = site_url($random['vid_src']);
		$postersrc = site_url($random['vid_poster']);
		$timer     = $random['vid_delay'];
		$buffer    = random_video_mdwsc( $buffer, $vidsrc, $postersrc, $timer );
	}

	return $buffer;
}

/**
 * @param $buffer
 *
 * @param $vidsrc
 * @param $postersrc
 * @param $timer
 *
 * @return mixed
 */
function random_video_mdwsc( $buffer, $vidsrc, $postersrc, $timer ) {
	// data-vide-bg=" is 14 characters long
//	$needle       = 'data-vide-bg="';
	$needle       = 'source src="';
	$start        = ( strpos( $buffer, $needle ) + strlen( $needle ) );
	$end          = strpos( $buffer, '"', $start );
	$videostr     = substr( $buffer, $start, ( $end - $start ) );
	$urls         = wp_extract_urls( $videostr );
	$curvidsrc    = $urls[0];
	$needle       = 'playsinline poster="';
	$start        = ( strpos( $buffer, $needle ) + strlen( $needle ) );
	$end          = strpos( $buffer, '"', $start );
	$posterstr     = substr( $buffer, $start, ( $end - $start ) );
	$urls         = wp_extract_urls( $posterstr );
	$curpostersrc = $urls[0];
	$buffer       = str_replace( $curvidsrc, $vidsrc, $buffer );
	$buffer       = str_replace( $curpostersrc, $postersrc, $buffer );

	$scriptData = array(
		'timer' => $timer,
	);
	wp_localize_script( 'mdwsc-full', 'videoObj', $scriptData );

	return $buffer;
}

function get_random_videos_mdwsc() {
	// multidimensional array - Associative Array 
	$videos = array(
		0  => array(
			'vid_src'=>'/wp-content/uploads/2016/10/vid0.mp4',
			'vid_poster'=>'/wp-content/uploads/2016/10/poster0.png',
			'vid_delay'=>'20000'
		),
		1  => array(
			'vid_src'=>'/wp-content/uploads/2016/10/vid1.mp4',
			'vid_poster'=>'/wp-content/uploads/2016/10/poster1.jpg',
			'vid_delay'=>'13000'
		),
		/* ... Code Removed for brevity ... */
		15 => array(
		'vid_src'=>'/wp-content/uploads/2016/10/vid15.mp4',
		'vid_poster'=>'/wp-content/uploads/2016/10/poster15.jpg',
		'vid_delay'=>'25000'
		)
	);

	$random       = $videos[ rand( 0, count( $videos ) - 1 ) ];

	return $random;
}

/**
 * Executed at the end of the header section of html.
 * The parameter, the callback_for_buffer_start_mdwsc function is
 * called at the end of the output buffering.  This occurs at the
 * footer of the page, when the second required action, buffer_end_mdwsc
 * executes.
 */
function buffer_start_mdwsc() {
	ob_start( "callback_for_buffer_start_mdwsc" );
}

/**
 * Allows page to be displayed
 */
function buffer_end_mdwsc() {
	ob_end_flush();
}

Line #87 is the most significant part of the code above.

ob_start( "callback_for_buffer_start_mdwsc" );

From the PHP Manual, “This function will turn output buffering on. While output buffering is active no output is sent from the script (other than headers), instead the output is stored in an internal buffer.”  The callback function manipulates the output stored in the internal buffer and returns the updated buffer.  Remember that we need to call this callback function buffer_start_mdwsc() from the add_action using the wp_head hook.  That means we are capturing everything up to the hook wp_footer (no footer, no sidebars, etc.). We then execute the hook add_action using wp_footer calling buffer_end_mdwsc().  At that point Line #93 is executed and the internal buffering ends with ob_end_flush();

Another significant piece of code is Line #34:

$urls         = wp_extract_urls( $videostr );

Up to that point the code extracts a string residing in an HTML source element with an attribute src.  The string looks something like “mp4:https://mdwsc.com/wp-content/uploads/2016/10/vid1.mp4, poster”,  The method wp_extract_urls($videostr) extracts just the URLs from the string stored in $videostr,  My reaction to that is: SWEET!

We then do a string replace of the video URL value and of the poster URL value we extracted from the multidimensional array using the random number we received from get_random_videos_mdwsc().  The values stored in the inner array are the video URL, the poster URL, and the delay time in milliseconds before we want the JavaScript to fire again.  Each video is of a variable length.  Now all we have to do is put a JSON object videoObj with a property timer that contains the delay value into the DOM so that the JavaScript can read it on page load.

Note the comment, Code Removed for brevity in the code above and below.  Remember that all of the index numbers in the outer array must be sequential and you can not skip one.

Here is the JavaScript code in mdwsc_full.js:

    var videos = [];
    videos[0] = ['/wp-content/uploads/2016/10/vid0.mp4',
        '/wp-content/uploads/2016/10/poster0.jpg',
        '20000'];
    videos[1] = ['/wp-content/uploads/2016/10/vid1.mp4',
        '/wp-content/uploads/2016/10/poster1.jpg',
        '13000'];
    // ... Code Removed for brevity ...
    videos[15] = ['/wp-content/uploads/2016/10/vid15.mp4',
        '/wp-content/uploads/2016/10/poster15.jpg', 
        '25000'];

    if (typeof videoObj != 'undefined') {
        if (videoObj.timer) {
            var delay = parseInt(videoObj.timer) ? parseInt(videoObj.timer) : 10000;
            // Math.floor(Math.random() * (max - min) + min); // min (inclusive) max (exclusive)
            function newVideo() {
                var idx = Math.floor(Math.random() * (16 - 0) + 0);
                var randvid = hostname + videos[idx][0];
                var randposter = hostname + videos[idx][1];
                delay = parseInt(videos[idx][2]) ? parseInt(videos[idx][2]) : 10000;
                var player = jQuery('video');
                player.get(0).pause();
                jQuery('video').attr('src', randvid);
                jQuery('video').attr('poster', randposter);
                player.get(0).play();
                timer = setTimeout(newVideo, delay);
            }
            var timer = setTimeout(newVideo, delay+10000);
        }
    }
}

This JavaScript code waits the appropriate delay time, then replaces the video source with the new URL and ,,, VOILA!  Another Random Video plays!

The Featured Image at the top of this page is the selected video for the About page.  However, I am amazed how seldom I see this video.  Oh yeah, I remember now, random is random – just saying!

Facebooktwitterredditpinterestlinkedinmail

Leave a Comment