Introduction

embedMedia is a php class for generating a standards compliant method of embedding multimedia content in a web page that will work in the vast majority of web browsers without needing to resort to JavaScript or browser sniffing.

The class uses DOMDocument and json_encode to generate the code and therefore generates code suitable for either HTML or XHTML documents that lends itself to further server side manipulation via DOMDocument tools before inclusion in the actual web page. The downside to using DOMDocument and json_encode is that you must have PHP 5.2.x or newer compiled against libxml2.

You *might* be able to get away with php 5.0.x or 5.1.x if you have built the json_encode PECL extension.

Three methods for embedding media are available from the class:

Dependencies

With the free GPL version of Flowplayer, the Flowplayer logo will appear on video content when Flowplayer is used. Purchase a commercial license to Flowplayer if you do not want this.

Flowplayer can be downloaded from http://flowplayer.org/
Audio plugin can be downloaded from http://flowplayer.org/plugins/streaming/audio.html

Unlike some plugins, the audio plugin does NOT require commercial license.

Flowplayer and the audio plugin are installed on your server. The end user does not need to install anything as long as they have flash.

Class Source

Using the Class

Initiating Class

<?php
require_once('xml_embedMedia.inc');
$foo = new DOMDocument('1.0','UTF-8');
$foo->preserveWhiteSpace = false;
$foo->formatOutput = true;
$media = new embedMedia($foo,'mySong','/media/mysong.mp3','/media/mysong.ogg','/media/mysong.wma');
$media->public = 'whatever'; // where public is the public variable you are
                             // setting to whatever
$mObject = $media->auto();
$foo->appendChild($mObject);
?>

To create an HTML fragment:

<?php
$string = preg_replace('/<\/source>/','',$foo->saveHTML());
print ($string);
?>

The preg_replace is not absolutely necessary. The issue is that libxml2 does not know about the (X)HTML 5 media source tag, that it never has child nodes and thus (like meta) should not have a closing tag.

To create an XHTML fragment:

<?php
$string = preg_replace('/.+\n/','',$foo->saveXML(),1);
print ($string);
?>

The preg_replace removes the
<?xml version="1.0" encoding="UTF-8"?>
that results from the DOMDocument->saveXML() function.

Of course if you are already using DOMDocument to construct your web page, you can just use your existing DOM object as the first argument to the embedMedia class and just append the resulting $mObject to your existing DOM and not have to worry about that.

Arguements

The class takes up to 5 arguments to initiate. Three of the arguments are required.

The first argument to embedMedia is the handle for your DOMDocument object. Required, must be a DOMDocument object.

The second argument is an identifier. Should not contain spaces. It is used to create an id attribute in the (X)HTML 5 media tag, the Flowplayer object tag, and the optional Windows Media object tag. Required. For pages with multiple pieces of embedded media, be careful not to use the same id twice in the same document.

The third argument is the path to either MP4 or MP3 version of media. Required. For video The MP4 version should be H.264/AVC. For audio the MP3 version should be MPEG 1 Layer 3.

The fourth argument is the path to the ogg version of the media. Optional. For video it should be Ogg Theora. For audio it should be Ogg Vorbis.

The fifth argument is the path to the windows media version. Optional.

Public Variables

public $width
Integer, the width of the embedded media. Defaults to 384.
public $height
Integer, the height of the embedded media. Defaults to 24. For (X)HTML 5 audio, the value is meaningless.
public $cbarheight
Integer, the height of the media control bar. Only meaningful to Flowplayer. Defaults to 24.
public $autoplay
Boolean, determines whether or not the media starts playing on page load. Defaults to false.
public $autobuffer
Boolean, determines whether or not the media starts buffering on page load. Defaults to false. Safari seems to ignore this with (X)HTML 5 media and uses the users QuickTime preferences instead.
public $controls
Boolean, determines whether or not to show control bar. Defaults to true.
public $type
audio or video. Specifies whether the media is audio content or video content. Defaults to audio.
public $poster
URL, Specifies path to image to use as a poster for media. If the type is audio, the poster will be displayed in Flowplayer while audio plays. Meaningless for (X)HTML 5 audio.
public $fullscreen
Boolean, whether or not Flowplayer control bar should have full screen button. Meaningless to (X)HTML 5 media. Defaults to false. Note that unless your video content is high definition (ie 720p), it probably will look bad at full screen. (X)HTML 5 video does not yet provide a uniform method for indicating full screen display, the web designer has no control over whether or not (X)HTML 5 video allows full screen presentation.
public $fplayer
URL, path in web root to Flowplayer. Defaults to /swf/Flowplayer-3.1.5.swf
public $faplayer
URL, path in web root to Flowplayer audio plugin, defaults to /swf/Flowplayer.audio-3.1.2.swf
public $fpkey
String, if you have the commercial version of Flowplayer, use this variable to specify your license key.
public $dnlWrap
URL, see section on ‘Download Wrapper’
public $wmpClassID
String, the classid for Windows Media Player. See section on Windows Media Player. Defaults to clsid:6BF52A52-394A-11D3-B153-00C04F79FAA6
public $h5class
String, CSS class to use with (X)HTML 5 media. Defaults to empty. If set, it defines the class attribute for the audio or video node.
public $fpclass
String, CSS class to use with Flowplayer. Defaults to empty. If set, it defines the class attribute for the Flowplayer object node.
public $wmclass
String, CSS class to use with Windows Media Player. Defaults to empty. If set, it defines the class attribute for the Windows Media object node.
public $fbclass
String, CSS class to use with plain text fallback if the browser does not support any of the embedded media options. Defaults to empty. If set, it defines the class attribute for the fallback paragraph node.

As you can see, there are a lot of public variables. You will probably want to define a custom class(es) that extends this class to suit your needs and predefine the public variables. For an example of how to do this, see the example file below:

Public Functions

public function embedMedia($dom,$id,$mpg,$ogg='',$wma='')
Constructor Function. After using the constructor function when initiating the object, use one of the following functions to generate your code fragment as a DOMDocument object:
public function html5()
Generates (X)HTML 5 media tags with flash (Flowplayer) as fallback.
public function flow()
Generates flash (Flowplayer) object tags with (X)HTML 5 media as fallback.
public function auto()
If Ogg version of file is given, returns same as html5(). Otherwise, returns same as flow()
public function windowsMedia()
I recommend against using this function unless you really must. Generates object code for Windows Media, and then uses auto() to generate fallback to Windows Media.

Class Notes

Download Wrapper

For direct download of media, including hyperlinks used as last ditch fallback in this class, it generally is better not to link directly to media. Some browsers will not start a download but either try to play the file in the browser window or show binary rubbish.

The solution to this dilemna is to use a php script as a wrapper to these media files that will send the proper attachment header and prompt the browser to download the media to disk.

That is where the $dnlWrap public variable comes in.

There are two commonly used solutions. The one I prefer is to create a directory containing nothing but the php wrapper script and a .htaccess file redirecting media requests to the php wrapper script:

RewriteEngine on
RewriteRule ^.+$ wrapper.php [L]

The wrapper.php then determines the desired file based upon $_SERVER['REQUEST_URI'], send the appropriate headers, reads the file into a buffer, and sends it.

To implement that solution with this class so that the fallback hyperlinks point to the directory containing the media wrapper, set the $dnlWrap public variable to the URI of the directory you are using. See the example of extending the class above for an example.

That solution is fairly dependent upon Apache configuration. Another solution is to pass the name of the requested media file to the wrapper as a GET variable. In this case, you would need to set the $dnlWrap public variable to the URI of the wrapper and the GET variable name. For example:

<?php
var $dnlWrap = '/media/dnl/wrapper.php?file=';
?>

MIME Types

Some HTML 5 media browsers seem to be sensitive of Ogg mime types, and some server installs do not send mime types that make them happy. Put the following in a .htaccess file in the directory that serves Ogg files to make sure it works properly:

AddType application/ogg .ogx
AddType audio/ogg .ogg
AddType video/ogg .ogv

Flowplayer Notes

Flowplayer code is done using the “Pure OBJECT tag” method detailed at http://flowplayer.org/demos/installation/alternate/index.html and does not use JavaScript.

Flowplayer is updated with some frequency. I suggest you check their web site regularly for updates. The updates primarily fix issues that crop up with Internet Explorer from time to time, but since IE is the only major browser that does not at least have (X)HTML 5 media support in development versions, you want to make sure the version of Flowplayer you have is up to date, especially after MS releases an IE update.

By extending the class, when you do update Flowplayer you can just update the extended class and do not need to update the class distributed here.

If you use the commercial version of Flowplayer, see the extend.embedMedia.inc shown above for an example of how to reference the commercial player and specify your license key.

Note that for Flowplayer to play H.264/AVC media, the browser needs to have flash 9.115 or newer installed. That usually is not a problem.

HTML 5 Media Notes

Unfortunately, there is no defined standard media type for HTML 5 media. If you include both MP3 and ogg versions of audio, any (X)HTML 5 media browser should handle it. If you only include MP3, then some browsers (IE FireFox) will not handle it, and unfortunately will not use the fallback either.

If you include both H.264/AVC (MP4) and Ogg Theora versions of video, any (X)HTML 5 media browser should handle it. If you only include the MP4, then some browsers (IE Firefox) will not handle it, and unfortunately will not use the fallback either.

For this reason, if you do not have Ogg versions of the media, it is suggested that you use the flow() function instead of the html5() function. You can also use the auto() function, and it will use flow() function by default if an Ogg file is not provided.

H.264 Streaming Notes

Most video encoders that produce H.264/AVC content do not properly set up the media for streaming. Additionally, many H.264/AVC meta data taggers break them for streaming.

The result is poor user experience, streaming media players will not begin to play the file until it has been completely downloaded.

The solution comes from ffmpeg, which has a program called qt-faststart in its contrib directory. Most distributions of ffmpeg should have that compiled for you. To use it:

cp yourfile.mp4 tmp.mp4
qt-faststart tmp.mp4 yourfile.mp4
rm tmp.mp4

Now yourfile.mp4 is properly set up for streaming, allowing playback to start before the media player has finished completely downloading the file.

Windows Media Notes

I only wrote the windowsMedia() function because I know of cases where the boss tells the web developer that Windows Media is to be used as the default media player, period. My suspicion is that this is to deal with corporate environments where IE on Windows is always the browser and Flash is removed from the computers for security and/or productivity reasons.

If you have such a mandate, use the windowsMedia() function. It will generate code that should trigger Windows Media Player if available, and it also uses the auto() function to generate fallback code for non IE browsers. I have not actually tested how well it works, I do not run Windows, but the generated code looks to me like it “should” do what I intended.

Unfortunately, some non IE browsers (IE Opera) will try to handle the media and sometimes fail without attempt to use the fall back, so I really suggest against using that function unless your job depends upon it.

Please note that not all installs of Windows Media Player support MP3 or H.264 decoding out of the box. If you use this function, it is best to specify a Windows Media version of the file when you initialize the class.

Examples

Example code snippets and the output generated:
example.php

Live pages that make use of the class:
Audio Example
Audio and Video Example

[W3C Valid]