wp_playlist_shortcode()WP 3.9.0

Gets the HTML code of the playlist from audio or video files for output in posts. Output parameters can be specified.

This function is the basis for processing the shortcode [playlist].

List of supported shortcodes in WordPress: [audio], [caption], [embed], [gallery], [playlist], [video]

Hooks from the function

Returns

String. HTMl code of the playlist. An empty string if the specified type is not supported.

Usage

wp_playlist_shortcode( $attr );
$attr(array) (required)

Array of output parameters for the playlist. Supports the following parameters:

  • type(string)
    Type of the output playlist: audio or video.
    Default: 'audio'

  • order(string)
    Direction of sorting the playlist items: ASC or DESC.
    Default: 'ASC'

  • orderby(string)
    Column or columns of the wp_posts table by which to sort the playlist items. If the ids parameter is specified, this parameter defaults to post__in, meaning to sort by the order of the specified IDs.
    For more details on possible values and this parameter in general, refer to the description of WP_Query.
    Default: 'menu_order ID'

  • id(int)
    ID of the post whose attachments will be collected in the playlist. If the ids parameter is specified, this parameter is ignored.
    Default: 0 (ID of the post from the global variable $post)

  • ids(array/string)
    ID of attachments from which to collect the playlist. Overrides the ID parameter. Can be specified as a string (IDs separated by commas) or as an array. For more details, see the include parameter from get_posts().
    Default: ''

  • exclude(array/string)
    List of attachment IDs to exclude from the list. Can be specified as a string (IDs separated by commas) or as an array.
    Default: ''

  • style(string)
    Styles for the appearance of the playlist: light or dark.
    Default: 'light'

  • tracklist(boolean)
    Show or hide the playlist.
    Default: true

  • tracknumbers(boolean)
    Show or not show the ordinal number of the playlist item.
    Default: true

  • images(boolean)
    Show or not show the thumbnail of the playlist item: audio or video.
    Default: true

  • artists(boolean)
    Show or not show the name of the artist of the playlist item.
    Default: true

About the WordPress shortcode [playlist]

Since version 3.9, WordPress supports the shortcode [playlist], which allows for convenient output of lists of audio or video files attached to a post. Here are various ways to call such a shortcode:

Basic call with default parameters. Will create a playlist of all audio files attached to the post:

[playlist]

Will change the playlist style to dark:

[playlist style="dark"]

Will change the file type from audio to video:

[playlist type="video"]

Let's specify the IDs of the audio files (attachments from the media library) from which the playlist will be assembled.

[playlist ids="123,456,789"]

Let's specify that the provided IDs are video files and change the style to dark:

[playlist type="video" ids="123,456,789" style="dark"]

Examples

0

#1 Display the audio playlist in the template

Suppose we need to display a playlist after the content, which will contain all the audio files attached to the posts. In other words, we need to do what the [playlist] shortcode does.

echo wp_playlist_shortcode();

The result is a playlist like this:

This is HTML code:

<div class="wp-playlist wp-audio-playlist wp-playlist-light">
	<div class="wp-playlist-current-item">

		<img src="http://example.com/wp-content/uploads/2016/05/Pixaliz-Hold-On-feat-Li0by-mp3-image-150x150.png" alt="">

		<div class="wp-playlist-caption">
			<span class="wp-playlist-item-meta wp-playlist-item-title">“Hold On (feat. Li0by)”</span>
			<span class="wp-playlist-item-meta wp-playlist-item-album">Outside EP</span>
			<span class="wp-playlist-item-meta wp-playlist-item-artist">Pixaliz</span>
		</div>
	</div>

	<span class="mejs-offscreen">Audio Player</span>

	<div id="mep_1" class="mejs-container svg mejs-audio" tabindex="0" role="application" aria-label="Audio Player" style="width: 481px; height: 30px;">
		<div class="mejs-inner">
			<div class="mejs-mediaelement">
				<audio preload="none" width="638" style="visibility: hidden; width: 100%; height: 100%;" src="http://example.com/wp-content/uploads/2016/05/Pixaliz-Hold-On-feat.-Li0by.mp3"></audio>
			</div>
			<div class="mejs-layers">
				<div class="mejs-poster mejs-layer" style="display: none; width: 100%; height: 100%;"></div>
			</div>
			<div class="mejs-controls">
				<div class="mejs-button mejs-playpause-button mejs-play">
					<button type="button" aria-controls="mep_1" title="Play" aria-label="Play"></button>
				</div>
				<div class="mejs-time mejs-currenttime-container" role="timer" aria-live="off"><span class="mejs-currenttime">00:00</span></div>
				<div class="mejs-time-rail" style="width: 307px;"><span class="mejs-time-total mejs-time-slider" style="width: 297px;"><span class="mejs-time-buffering" style="display: none;"></span><span class="mejs-time-loaded"></span><span class="mejs-time-current"></span><span class="mejs-time-handle"></span><span class="mejs-time-float" style="display: none;"><span class="mejs-time-float-current">00:00</span><span class="mejs-time-float-corner"></span></span>
					</span>
				</div>
				<div class="mejs-time mejs-duration-container"><span class="mejs-duration">00:00</span></div>
				<div class="mejs-button mejs-volume-button mejs-mute">
					<button type="button" aria-controls="mep_1" title="Mute" aria-label="Mute"></button>
				</div><a href="javascript:void(0);" class="mejs-horizontal-volume-slider mejs-mute" aria-label="volumeSlider" aria-valuemin="0" aria-valuemax="100" aria-valuenow="80" aria-valuetext="80%" role="slider" tabindex="0"><span class="mejs-offscreen">Use Up/Down Arrow keys to increase or decrease volume.</span><div class="mejs-horizontal-volume-total"></div><div class="mejs-horizontal-volume-current" style="width: 40px;"></div><div class="mejs-horizontal-volume-handle" style="left: 27px;"></div></a></div>
			<div class="mejs-clear"></div>
		</div>
	</div>

	<div class="wp-playlist-next"></div>
	<div class="wp-playlist-prev"></div>

	<noscript>
		<ol><li><a href='http://example.com/wp-content/uploads/2016/05/Pixaliz-Hold-On-feat.-Li0by.mp3'>Hold On (feat. Li0by)</a></li><li><a href='http://example.com/wp-content/uploads/2016/05/Pixaliz-Nocturne.mp3'>Nocturne</a></li><li><a href='http://example.com/wp-content/uploads/2016/05/Pixaliz-Outside.mp3'>Outside</a></li></ol>
	</noscript>
	<script type="application/json" class="wp-playlist-script">{"type":"audio","tracklist":true,"tracknumbers":true,"images":true,"artists":true,"tracks":[{"src":"http:\/\/example.com\/wp-content\/uploads\/2016\/05\/Pixaliz-Hold-On-feat.-Li0by.mp3","type":"audio\/mpeg","title":"Hold On (feat. Li0by)","caption":"","description":"\"Hold On (feat. Li0by)\" from Outside EP by Pixaliz. Released: 2016. Track 2. Genre: French Touch.","meta":{"artist":"Pixaliz","album":"Outside EP","genre":"French Touch","year":"2016","length_formatted":"3:10"},"image":{"src":"http:\/\/example.com\/wp-content\/uploads\/2016\/05\/Pixaliz-Hold-On-feat-Li0by-mp3-image.png","width":500,"height":500},"thumb":{"src":"http:\/\/example.com\/wp-content\/uploads\/2016\/05\/Pixaliz-Hold-On-feat-Li0by-mp3-image-150x150.png","width":150,"height":150}},{"src":"http:\/\/example.com\/wp-content\/uploads\/2016\/05\/Pixaliz-Nocturne.mp3","type":"audio\/mpeg","title":"Nocturne","caption":"","description":"\"Nocturne\" from Outside EP by Pixaliz. Released: 2016. Track 3. Genre: French Touch.","meta":{"artist":"Pixaliz","album":"Outside EP","genre":"French Touch","year":"2016","length_formatted":"3:35"},"image":{"src":"http:\/\/example.com\/wp-content\/uploads\/2016\/05\/Pixaliz-Hold-On-feat-Li0by-mp3-image.png","width":500,"height":500},"thumb":{"src":"http:\/\/example.com\/wp-content\/uploads\/2016\/05\/Pixaliz-Hold-On-feat-Li0by-mp3-image-150x150.png","width":150,"height":150}},{"src":"http:\/\/example.com\/wp-content\/uploads\/2016\/05\/Pixaliz-Outside.mp3","type":"audio\/mpeg","title":"Outside","caption":"","description":"\"Outside\" from Outside EP by Pixaliz. Released: 2016. Track 4. Genre: French Touch.","meta":{"artist":"Pixaliz","album":"Outside EP","genre":"French Touch","year":"2016","length_formatted":"4:15"},"image":{"src":"http:\/\/example.com\/wp-content\/uploads\/2016\/05\/Pixaliz-Outside-mp3-image.png","width":500,"height":500},"thumb":{"src":"http:\/\/example.com\/wp-content\/uploads\/2016\/05\/Pixaliz-Outside-mp3-image-150x150.png","width":150,"height":150}}]}</script>

	<div class="wp-playlist-tracks">
		<div class="wp-playlist-item wp-playlist-playing">
			<a class="wp-playlist-caption" href="http://example.com/wp-content/uploads/2016/05/Pixaliz-Hold-On-feat.-Li0by.mp3">
				1. <span class="wp-playlist-item-title">“Hold On (feat. Li0by)”</span> <span class="wp-playlist-item-artist"> — Pixaliz</span>
			</a>

			<div class="wp-playlist-item-length">3:10</div>
		</div>

		<div class="wp-playlist-item">
			<a class="wp-playlist-caption" href="http://example.com/wp-content/uploads/2016/05/Pixaliz-Nocturne.mp3">
				2.  <span class="wp-playlist-item-title">“Nocturne”</span> <span class="wp-playlist-item-artist"> — Pixaliz</span>
			</a>

			<div class="wp-playlist-item-length">3:35</div>
		</div>

		<div class="wp-playlist-item">
			<a class="wp-playlist-caption" href="http://example.com/wp-content/uploads/2016/05/Pixaliz-Outside.mp3">
				3. <span class="wp-playlist-item-title">“Outside”</span> <span class="wp-playlist-item-artist"> — Pixaliz</span>
			</a>

			<div class="wp-playlist-item-length">4:15</div>
		</div>
	</div>
</div>

This is what a dark theme looks like:

0

#2 Display the playlist of the specified video files

Let's say we know the IDs of the videos added to the media library, which are 54,132. And now, we need to list these videos in black design (with dark theme).

$attr = array(
	'type'  => 'video',
	'ids'   => '54,132',
	'style' => 'dark', 
);

echo wp_playlist_shortcode( $attr );

The result is:

HTML code:

<!--[if lt IE 9]><script>document.createElement('video');</script><![endif]-->
<div class="wp-playlist wp-video-playlist wp-playlist-light">
<span class="mejs-offscreen">Video Player</span>
	<div id="mep_0" class="mejs-container svg mejs-video" tabindex="0" role="application" aria-label="Video Player" style="width: 481px; height: 253px;">
		<div class="mejs-inner">
			<div class="mejs-mediaelement">
				<div class="me-cannotplay" style="width: 638px; height: 336px;"><a href="http://example.com/wp-content/uploads/2016/05/Video_2016-05-20_154705.wmv"><span>Download File</span></a></div>
				<video preload="none" width="638" height="336" src="http://example.com/wp-content/uploads/2016/05/Video_2016-05-20_154705.wmv" style="width: 100%; height: 100%; display: none;"></video>
			</div>
			<div class="mejs-layers"></div>
			<div class="mejs-controls" style="display: none;"></div>
			<div class="mejs-clear"></div>
		</div>
	</div>

	<div class="wp-playlist-next"></div>
	<div class="wp-playlist-prev"></div>

	<noscript>
	<ol><li><a href='http://example.com/wp-content/uploads/2016/05/Video_2016-05-20_154705.wmv'>Video 1</a></li><li><a href='http://example.com/wp-content/uploads/2016/05/Video_2016-05-12_212534.wmv'>Video 2</a></li></ol>
	</noscript>
	<script type="application/json" class="wp-playlist-script">{"type":"video","tracklist":true,"tracknumbers":true,"images":true,"artists":true,"tracks":[{"src":"http:\/\/example.com\/wp-content\/uploads\/2016\/05\/Video_2016-05-20_154705.wmv","type":"video\/x-ms-wmv","title":"\u0412\u0438\u0434\u0435\u043e 1","caption":"","description":"","meta":{"length_formatted":"2:08"},"dimensions":{"original":{"width":1904,"height":1004},"resized":{"width":638,"height":336}},"image":{"src":"http:\/\/example.com\/wp\/wp-includes\/images\/media\/video.png","width":48,"height":64},"thumb":{"src":"http:\/\/example.com\/wp\/wp-includes\/images\/media\/video.png","width":48,"height":64}},{"src":"http:\/\/example.com\/wp-content\/uploads\/2016\/05\/Video_2016-05-12_212534.wmv","type":"video\/x-ms-wmv","title":"\u0412\u0438\u0434\u0435\u043e 2","caption":"","description":"","meta":{"length_formatted":"2:24"},"dimensions":{"original":{"width":1356,"height":660},"resized":{"width":638,"height":311}},"image":{"src":"http:\/\/example.com\/wp\/wp-includes\/images\/media\/video.png","width":48,"height":64},"thumb":{"src":"http:\/\/example.com\/wp\/wp-includes\/images\/media\/video.png","width":48,"height":64}}]}</script>

	<div class="wp-playlist-tracks">
		<div class="wp-playlist-item wp-playlist-playing">
			<a class="wp-playlist-caption" href="http://example.com/wp-content/uploads/2016/05/Video_2016-05-20_154705.wmv">
				1. <span class="wp-playlist-item-title"> "Video 1"</span>
			</a>

			<div class="wp-playlist-item-length">2:08</div>
		</div>

		<div class="wp-playlist-item">
			<a class="wp-playlist-caption" href="http://example.com/wp-content/uploads/2016/05/Video_2016-05-12_212534.wmv">
				2. <span class="wp-playlist-item-title"> "Video 2"</span>
			</a>

			<div class="wp-playlist-item-length">2:24</div>
		</div>
	</div>
</div>

This is what light looks like:

0

#3 Completely override output

The function can be completely overridden by the hook post_playlist. Exactly as it is done with the gallery shortcode in the example function gallery_shortcode()

add_filter( 'post_playlist', 'my_playlist_shortcode', 10, 3 );

function my_playlist_shortcode( $empty_str, $attr, $instance ){

	// check what we need, and if it fits, redefine the entire wp_playlist_shortcode function
	if( $attr['type'] !== 'video' ){
		return '';
	}

	// here we write our own code to output the playlist for video files
}

Notes

  • Global. Int. $content_width

Changelog

Since 3.9.0 Introduced.

wp_playlist_shortcode() code WP 6.9

<?php
function wp_playlist_shortcode( $attr ) {
	global $content_width;
	$post = get_post();

	static $instance = 0;
	++$instance;

	static $is_loaded = false;

	if ( ! empty( $attr['ids'] ) ) {
		// 'ids' is explicitly ordered, unless you specify otherwise.
		if ( empty( $attr['orderby'] ) ) {
			$attr['orderby'] = 'post__in';
		}
		$attr['include'] = $attr['ids'];
	}

	/**
	 * Filters the playlist output.
	 *
	 * Returning a non-empty value from the filter will short-circuit generation
	 * of the default playlist output, returning the passed value instead.
	 *
	 * @since 3.9.0
	 * @since 4.2.0 The `$instance` parameter was added.
	 *
	 * @param string $output   Playlist output. Default empty.
	 * @param array  $attr     An array of shortcode attributes.
	 * @param int    $instance Unique numeric ID of this playlist shortcode instance.
	 */
	$output = apply_filters( 'post_playlist', '', $attr, $instance );

	if ( ! empty( $output ) ) {
		return $output;
	}

	$atts = shortcode_atts(
		array(
			'type'         => 'audio',
			'order'        => 'ASC',
			'orderby'      => 'menu_order ID',
			'id'           => $post ? $post->ID : 0,
			'include'      => '',
			'exclude'      => '',
			'style'        => 'light',
			'tracklist'    => true,
			'tracknumbers' => true,
			'images'       => true,
			'artists'      => true,
		),
		$attr,
		'playlist'
	);

	$id = (int) $atts['id'];

	if ( 'audio' !== $atts['type'] ) {
		$atts['type'] = 'video';
	}

	$args = array(
		'post_status'    => 'inherit',
		'post_type'      => 'attachment',
		'post_mime_type' => $atts['type'],
		'order'          => $atts['order'],
		'orderby'        => $atts['orderby'],
	);

	if ( ! empty( $atts['include'] ) ) {
		$args['include'] = $atts['include'];
		$_attachments    = get_posts( $args );

		$attachments = array();
		foreach ( $_attachments as $key => $val ) {
			$attachments[ $val->ID ] = $_attachments[ $key ];
		}
	} elseif ( ! empty( $atts['exclude'] ) ) {
		$args['post_parent'] = $id;
		$args['exclude']     = $atts['exclude'];
		$attachments         = get_children( $args );
	} else {
		$args['post_parent'] = $id;
		$attachments         = get_children( $args );
	}

	if ( ! empty( $args['post_parent'] ) ) {
		$post_parent = get_post( $id );

		// Terminate the shortcode execution if the user cannot read the post or it is password-protected.
		if ( ! current_user_can( 'read_post', $post_parent->ID ) || post_password_required( $post_parent ) ) {
			return '';
		}
	}

	if ( empty( $attachments ) ) {
		return '';
	}

	if ( is_feed() ) {
		$output = "\n";
		foreach ( $attachments as $att_id => $attachment ) {
			$output .= wp_get_attachment_link( $att_id ) . "\n";
		}
		return $output;
	}

	$outer = 22; // Default padding and border of wrapper.

	$default_width  = 640;
	$default_height = 360;

	$theme_width  = empty( $content_width ) ? $default_width : ( $content_width - $outer );
	$theme_height = empty( $content_width ) ? $default_height : round( ( $default_height * $theme_width ) / $default_width );

	$data = array(
		'type'         => $atts['type'],
		// Don't pass strings to JSON, will be truthy in JS.
		'tracklist'    => wp_validate_boolean( $atts['tracklist'] ),
		'tracknumbers' => wp_validate_boolean( $atts['tracknumbers'] ),
		'images'       => wp_validate_boolean( $atts['images'] ),
		'artists'      => wp_validate_boolean( $atts['artists'] ),
	);

	$tracks = array();
	foreach ( $attachments as $attachment ) {
		$url   = wp_get_attachment_url( $attachment->ID );
		$ftype = wp_check_filetype( $url, wp_get_mime_types() );
		$track = array(
			'src'         => $url,
			'type'        => $ftype['type'],
			'title'       => $attachment->post_title,
			'caption'     => $attachment->post_excerpt,
			'description' => $attachment->post_content,
		);

		$track['meta'] = array();
		$meta          = wp_get_attachment_metadata( $attachment->ID );
		if ( ! empty( $meta ) ) {

			foreach ( wp_get_attachment_id3_keys( $attachment ) as $key => $label ) {
				if ( ! empty( $meta[ $key ] ) ) {
					$track['meta'][ $key ] = $meta[ $key ];
				}
			}

			if ( 'video' === $atts['type'] ) {
				if ( ! empty( $meta['width'] ) && ! empty( $meta['height'] ) ) {
					$width        = $meta['width'];
					$height       = $meta['height'];
					$theme_height = round( ( $height * $theme_width ) / $width );
				} else {
					$width  = $default_width;
					$height = $default_height;
				}

				$track['dimensions'] = array(
					'original' => compact( 'width', 'height' ),
					'resized'  => array(
						'width'  => $theme_width,
						'height' => $theme_height,
					),
				);
			}
		}

		if ( $atts['images'] ) {
			$thumb_id = get_post_thumbnail_id( $attachment->ID );
			if ( ! empty( $thumb_id ) ) {
				list( $src, $width, $height ) = wp_get_attachment_image_src( $thumb_id, 'full' );
				$track['image']               = compact( 'src', 'width', 'height' );
				list( $src, $width, $height ) = wp_get_attachment_image_src( $thumb_id, 'thumbnail' );
				$track['thumb']               = compact( 'src', 'width', 'height' );
			} else {
				$src            = wp_mime_type_icon( $attachment->ID, '.svg' );
				$width          = 48;
				$height         = 64;
				$track['image'] = compact( 'src', 'width', 'height' );
				$track['thumb'] = compact( 'src', 'width', 'height' );
			}
		}

		$tracks[] = $track;
	}
	$data['tracks'] = $tracks;

	$safe_type  = esc_attr( $atts['type'] );
	$safe_style = esc_attr( $atts['style'] );

	ob_start();

	if ( ! $is_loaded ) {
		/**
		 * Prints and enqueues playlist scripts, styles, and JavaScript templates.
		 *
		 * @since 3.9.0
		 *
		 * @param string $type  Type of playlist. Possible values are 'audio' or 'video'.
		 * @param string $style The 'theme' for the playlist. Core provides 'light' and 'dark'.
		 */
		do_action( 'wp_playlist_scripts', $atts['type'], $atts['style'] );
		$is_loaded = true;
	}
	?>
<div class="wp-playlist wp-<?php echo $safe_type; ?>-playlist wp-playlist-<?php echo $safe_style; ?>">
	<?php if ( 'audio' === $atts['type'] ) : ?>
		<div class="wp-playlist-current-item"></div>
	<?php endif; ?>
	<<?php echo $safe_type; ?> controls="controls" preload="none" width="<?php echo (int) $theme_width; ?>"
		<?php
		if ( 'video' === $safe_type ) {
			echo ' height="', (int) $theme_height, '"';
		}
		?>
	></<?php echo $safe_type; ?>>
	<div class="wp-playlist-next"></div>
	<div class="wp-playlist-prev"></div>
	<noscript>
	<ol>
		<?php
		foreach ( $attachments as $att_id => $attachment ) {
			printf( '<li>%s</li>', wp_get_attachment_link( $att_id ) );
		}
		?>
	</ol>
	</noscript>
	<script type="application/json" class="wp-playlist-script"><?php echo wp_json_encode( $data, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ); ?></script>
</div>
	<?php
	return ob_get_clean();
}