wp_playlist_shortcode()WP 3.9.0

Builds the Playlist shortcode output.

This implements the functionality of the playlist shortcode for displaying a collection of WordPress audio or video files in a post.

Hooks from the function

Return

String. Playlist output. Empty string if the passed type is unsupported.

Usage

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

Array of default playlist attributes.

  • type(string)
    Type of playlist to display. Accepts 'audio' or 'video'.
    Default: 'audio'

  • order(string)
    Designates ascending or descending order of items in the playlist. Accepts 'ASC', 'DESC'.
    Default: 'ASC'

  • orderby(string)
    Any column, or columns, to sort the playlist. If $ids are passed, this defaults to the order of the $ids array ('post__in'). Otherwise default is 'menu_order ID'.

  • id(int)
    If an explicit $ids array is not present, this parameter will determine which attachments are used for the playlist.
    Default: current post ID

  • ids(array)
    Create a playlist out of these explicit attachment IDs. If empty, a playlist will be created from all $type attachments of $id.
    Default: ''

  • exclude(array)
    List of specific attachment IDs to exclude from the playlist.
    Default: ''

  • style(string)
    Playlist style to use. Accepts 'light' or 'dark'.
    Default: 'light'

  • tracklist(true|false)
    Whether to show or hide the playlist.
    Default: true

  • tracknumbers(true|false)
    Whether to show or hide the numbers next to entries in the playlist.
    Default: true

  • images(true|false)
    Show or hide the video or audio thumbnail (Featured Image/post thumbnail).
    Default: true

  • artists(true|false)
    Whether to show or hide artist name in the playlist.
    Default: true

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.7.1

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

	static $instance = 0;
	++$instance;

	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 ( 1 === $instance ) {
		/**
		 * 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'] );
	}
	?>
<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 ); ?></script>
</div>
	<?php
	return ob_get_clean();
}