Making a better audio shortcode for WordPress
If you use WordPress, you can get a fairly basic embedded audio player by using the audio shortcode:
[
audio mp3="/path/to/file.mp3"]
I didn't particularly like how it was styled so - because WordPress is so hackable - I changed it!
Now my embedded audio looks like this:
It gets a nice border, a title, displays any attached image, and uses the native HTML5 audio element.
Here's the code to do it. Stick it in your functions.php
and add suitable CSS. Shout if you spot any weird bugs.
PHPadd_filter('wp_audio_shortcode_override', 'edent_audio_shortcode_override', 10, 2);
function edent_audio_shortcode_override( $html, $attr ) {
$audio_url = "";
// The shortcode will have an attribute with the URl to the file:
// e.g. [ audio mp3="https://example.com/path/to/file.mp3" ]
if ( isset( $attr['wav'] ) ) { $audio_url = $attr['wav']; }
if ( isset( $attr['mp3'] ) ) { $audio_url = $attr['mp3']; }
if ( isset( $attr['m4a'] ) ) { $audio_url = $attr['m4a']; }
if ( isset( $attr['ogg'] ) ) { $audio_url = $attr['ogg']; }
if ( isset( $attr['opus'] ) ) { $audio_url = $attr['opus']; };
if ( isset( $attr['src'] ) ) { $audio_url = $attr['src']; }; // For raw links without a shortcode
// Defaults
$audio_meta = null;
$audio_thumb = false;
// Get the attachment ID from the media library
$audio_id = attachment_url_to_postid( $audio_url );
if ($audio_id > 0) {
$audio_meta = wp_get_attachment_metadata($audio_id);
$audio_thumb = get_the_post_thumbnail_url( $audio_id );
} else {
// Is this on our server?
$upload_dir = wp_upload_dir(); // Get the upload directory info
$upload_baseurl = $upload_dir['baseurl'];
// Check if the provided URL belongs to the site
if (strpos($audio_url, $upload_baseurl) !== false) {
// URL belongs to the site, get the file path
$file_path = str_replace($upload_baseurl, $upload_dir['basedir'], $audio_url);
// Check if the file exists on disk
if (file_exists($file_path)) {
require_once ABSPATH . 'wp-admin/includes/media.php';
$audio_meta = wp_read_audio_metadata( $file_path );
$audio_thumb = false;
}
}
}
// Get the title of the audio - or use a default
if ( isset( $audio_meta["title"] ) ) {
$audio_title = "🔊 " . htmlspecialchars( $audio_meta["title"], ENT_NOQUOTES | ENT_HTML5 | ENT_SUBSTITUTE, 'UTF-8', /*double_encode*/false );
} else {
$audio_title = "🔊";
}
// Get the artist of the audio - or use a default
if ( isset( $audio_meta["artist"] ) ) {
$audio_artist = "<br>🎤 " . htmlspecialchars( $audio_meta["artist"], ENT_NOQUOTES | ENT_HTML5 | ENT_SUBSTITUTE, 'UTF-8', /*double_encode*/false );
} else {
$audio_artist = "";
}
// Set the HTML for the thumbnail
if ( $audio_thumb ) {
$audio_thumb_html = "<img src=\"{$audio_thumb}\" class=\"audio-thumb\" alt=\"\">";
} else {
$audio_thumb_html = "";
}
$audio_html = <<<EOT
<figure class="audio">
<figcaption class="audio">{$audio_title}{$audio_artist}</figcaption>
{$audio_thumb_html}
<audio class="audio-player" controls src="{$audio_url}">
<a href="{$audio_url}">Download audio</a>
</audio>
</figure>
EOT;
return $audio_html;
}
How it works
I'm indebted to this answer on WordPress StackExchange and this one onStackOverflow.
There's a whole bunch of metadata available in the audio files.
But to start with, you need to take the URl of the audio source and find its ID in the media library.
attachment_url_to_postid( "https://example.com/path/to/file.mp3" );
That should give you an ID. And here's how to get all the metadata from that attachment ID: wp_get_attachment_metadata( 1234 )
Which spits out:
PHParray(25) {
["dataformat"]=> string(3) "mp3"
["channels"]=> int(1)
["sample_rate"]=> int(44100)
["bitrate"]=> float(63731.43187641008)
["channelmode"]=> string(4) "mono"
["bitrate_mode"]=> string(3) "vbr"
["codec"]=> string(4) "LAME"
["encoder"]=> string(8) "LAME3.97"
["lossless"]=> bool(false)
["encoder_options"]=> string(41) "--preset fast medium -b64 --lowpass 17500"
["compression_ratio"]=> float(0.09032232408788277)
["fileformat"]=> string(3) "mp3"
["filesize"]=> int(5714048)
["mime_type"]=> string(10) "audio/mpeg"
["length"]=> int(683)
["length_formatted"]=> string(5) "11:23"
["title"]=> string(55) "Location Based QR Codes - Introducing http://xmts.mobi/"
["artist"]=> string(5) "edent"
["copyright_message"]=> string(5) "edent"
["time"]=> string(4) "0549"
["date"]=> string(4) "0310"
["year"]=> string(4) "2010"
["encoded_by"]=> string(18) "http://audioboo.fm"
["image"]=> array(3) {
["mime"]=> string(9) "image/png"
["width"]=> int(826)
["height"]=> int(1169)
}
["album"]=> string(0) ""
}
You'll notice that it doesn't actually have the image data inside. If WordPress noticed there was an embedded image in the audio on upload, it will be attached to it as a featured image. You can get it using: get_the_post_thumbnail( 1234 );
Alternative, you can get the binary data for the image using the path to the file: wp_read_audio_metadata("wp-content/uploads/2010/11/1234.mp3");
This gives:
PHParray(24) {
["dataformat"]=> string(3) "mp3"
["channels"]=> int(1)
["sample_rate"]=> int(44100)
["bitrate"]=> float(63731.43187641008)
["channelmode"]=> string(4) "mono"
["bitrate_mode"]=> string(3) "vbr"
["codec"]=> string(4) "LAME"
["encoder"]=> string(8) "LAME3.97"
["lossless"]=> bool(false)
["encoder_options"]=> string(41) "--preset fast medium -b64 --lowpass 17500"
["compression_ratio"]=> float(0.09032232408788277)
["fileformat"]=> string(3) "mp3"
["filesize"]=> int(5714048)
["mime_type"]=> string(10) "audio/mpeg"
["length"]=> int(683)
["length_formatted"]=> string(5) "11:23"
["title"]=> string(55) "Location Based QR Codes - Introducing http://xmts.mobi/"
["artist"]=> string(5) "edent"
["copyright_message"]=> string(5) "edent"
["time"]=> string(4) "0549"
["date"]=> string(4) "0310"
["year"]=> string(4) "2010"
["encoded_by"]=> string(18) "http://audioboo.fm"
["image"]=> array(4) {
["data"]=> BINARY DATA
["mime"]=> string(9) "image/png"
["width"]=> int(826)
["height"]=> int(1169)
}
}
See wp_read_audio_metadata()
for more details. Note, it only works on local files - no reading from remote files.
ferrie=differentieel says:
nice code - missing the FLAC audio format - use that one often
More comments on Mastodon.