Title: wp_playlist_shortcode
Published: April 25, 2014
Last modified: August 20, 2026

---

# wp_playlist_shortcode( array $attr ): string

## In this article

 * [Description](https://developer.wordpress.org/reference/functions/wp_playlist_shortcode/?output_format=md#description)
 * [Parameters](https://developer.wordpress.org/reference/functions/wp_playlist_shortcode/?output_format=md#parameters)
 * [Return](https://developer.wordpress.org/reference/functions/wp_playlist_shortcode/?output_format=md#return)
 * [Source](https://developer.wordpress.org/reference/functions/wp_playlist_shortcode/?output_format=md#source)
 * [Hooks](https://developer.wordpress.org/reference/functions/wp_playlist_shortcode/?output_format=md#hooks)
 * [Related](https://developer.wordpress.org/reference/functions/wp_playlist_shortcode/?output_format=md#related)
 * [Changelog](https://developer.wordpress.org/reference/functions/wp_playlist_shortcode/?output_format=md#changelog)
 * [User Contributed Notes](https://developer.wordpress.org/reference/functions/wp_playlist_shortcode/?output_format=md#user-contributed-notes)

[ Back to top](https://developer.wordpress.org/reference/functions/wp_playlist_shortcode/?output_format=md#wp--skip-link--target)

Builds the Playlist shortcode output.

## 󠀁[Description](https://developer.wordpress.org/reference/functions/wp_playlist_shortcode/?output_format=md#description)󠁿

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

## 󠀁[Parameters](https://developer.wordpress.org/reference/functions/wp_playlist_shortcode/?output_format=md#parameters)󠁿

 `$attr`arrayrequired

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 is the 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 empty.
 * `exclude` array
 * List of specific attachment IDs to exclude from the playlist. Default empty.
 * `style` string
 * Playlist style to use. Accepts `'light'` or `'dark'`. Default `'light'`.
 * `tracklist` bool
 * Whether to show or hide the playlist. Default true.
 * `tracknumbers` bool
 * Whether to show or hide the numbers next to entries in the playlist. Default 
   true.
 * `images` bool
 * Show or hide the video or audio thumbnail (Featured Image/post thumbnail). Default
   true.
 * `artists` bool
 * Whether to show or hide artist name in the playlist. Default true.

## 󠀁[Return](https://developer.wordpress.org/reference/functions/wp_playlist_shortcode/?output_format=md#return)󠁿

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

## 󠀁[Source](https://developer.wordpress.org/reference/functions/wp_playlist_shortcode/?output_format=md#source)󠁿

    ```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 ) ) {
    				$image_src_full = wp_get_attachment_image_src( $thumb_id, 'full' );
    				if ( is_array( $image_src_full ) ) {
    					$track['image'] = array(
    						'src'    => $image_src_full[0],
    						'width'  => $image_src_full[1],
    						'height' => $image_src_full[2],
    					);
    				}

    				$image_src_thumb = wp_get_attachment_image_src( $thumb_id, 'thumbnail' );
    				if ( is_array( $image_src_thumb ) ) {
    					$track['thumb'] = array(
    						'src'    => $image_src_thumb[0],
    						'width'  => $image_src_thumb[1],
    						'height' => $image_src_thumb[2],
    					);
    				}
    			} 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();
    }
    ```

[View all references](https://developer.wordpress.org/reference/files/wp-includes/media.php/)
[View on Trac](https://core.trac.wordpress.org/browser/tags/7.1/src/wp-includes/media.php#L3192)
[View on GitHub](https://github.com/WordPress/wordpress-develop/blob/7.1/src/wp-includes/media.php#L3192-L3434)

## 󠀁[Hooks](https://developer.wordpress.org/reference/functions/wp_playlist_shortcode/?output_format=md#hooks)󠁿

 [apply_filters( ‘post_playlist’, string $output, array $attr, int $instance )](https://developer.wordpress.org/reference/hooks/post_playlist/)

Filters the playlist output.

 [do_action( ‘wp_playlist_scripts’, string $type, string $style )](https://developer.wordpress.org/reference/hooks/wp_playlist_scripts/)

Prints and enqueues playlist scripts, styles, and JavaScript templates.

## 󠀁[Related](https://developer.wordpress.org/reference/functions/wp_playlist_shortcode/?output_format=md#related)󠁿

| Uses | Description | 
| [get_children()](https://developer.wordpress.org/reference/functions/get_children/)`wp-includes/post.php` |

Retrieves all children of the post parent ID.

  | 
| [wp_validate_boolean()](https://developer.wordpress.org/reference/functions/wp_validate_boolean/)`wp-includes/functions.php` |

Filters/validates a variable as a boolean.

  | 
| [is_feed()](https://developer.wordpress.org/reference/functions/is_feed/)`wp-includes/query.php` |

Determines whether the query is for a feed.

  | 
| [wp_check_filetype()](https://developer.wordpress.org/reference/functions/wp_check_filetype/)`wp-includes/functions.php` |

Retrieves the file type from the file name.

  | 
| [wp_get_mime_types()](https://developer.wordpress.org/reference/functions/wp_get_mime_types/)`wp-includes/functions.php` |

Retrieves the list of mime types and file extensions.

  | 
| [shortcode_atts()](https://developer.wordpress.org/reference/functions/shortcode_atts/)`wp-includes/shortcodes.php` |

Combines user attributes with known attributes and fill in defaults when needed.

  | 
| [get_post_thumbnail_id()](https://developer.wordpress.org/reference/functions/get_post_thumbnail_id/)`wp-includes/post-thumbnail-template.php` |

Retrieves the post thumbnail ID.

  | 
| [wp_get_attachment_link()](https://developer.wordpress.org/reference/functions/wp_get_attachment_link/)`wp-includes/post-template.php` |

Retrieves an attachment page link using an image or icon, if possible.

  | 
| [post_password_required()](https://developer.wordpress.org/reference/functions/post_password_required/)`wp-includes/post-template.php` |

Determines whether the post requires password and whether a correct password has been provided.

  | 
| [wp_get_attachment_id3_keys()](https://developer.wordpress.org/reference/functions/wp_get_attachment_id3_keys/)`wp-includes/media.php` |

Returns useful keys to use to lookup data from an attachment’s stored metadata.

  | 
| [wp_get_attachment_image_src()](https://developer.wordpress.org/reference/functions/wp_get_attachment_image_src/)`wp-includes/media.php` |

Retrieves an image to represent an attachment.

  | 
| [wp_mime_type_icon()](https://developer.wordpress.org/reference/functions/wp_mime_type_icon/)`wp-includes/post.php` |

Retrieves the icon for a MIME type or attachment.

  | 
| [wp_get_attachment_url()](https://developer.wordpress.org/reference/functions/wp_get_attachment_url/)`wp-includes/post.php` |

Retrieves the URL for an attachment.

  | 
| [wp_get_attachment_metadata()](https://developer.wordpress.org/reference/functions/wp_get_attachment_metadata/)`wp-includes/post.php` |

Retrieves attachment metadata for attachment ID.

  | 
| [get_posts()](https://developer.wordpress.org/reference/functions/get_posts/)`wp-includes/post.php` |

Retrieves an array of the latest posts, or posts matching the given criteria.

  | 
| [wp_json_encode()](https://developer.wordpress.org/reference/functions/wp_json_encode/)`wp-includes/functions.php` |

Encodes a variable into JSON, with some confidence checks.

  | 
| [current_user_can()](https://developer.wordpress.org/reference/functions/current_user_can/)`wp-includes/capabilities.php` |

Returns whether the current user has the specified capability.

  | 
| [esc_attr()](https://developer.wordpress.org/reference/functions/esc_attr/)`wp-includes/formatting.php` |

Escaping for HTML attributes.

  | 
| [apply_filters()](https://developer.wordpress.org/reference/functions/apply_filters/)`wp-includes/plugin.php` |

Calls the callback functions that have been added to a filter hook.

  | 
| [do_action()](https://developer.wordpress.org/reference/functions/do_action/)`wp-includes/plugin.php` |

Calls the callback functions that have been added to an action hook.

  | 
| [get_post()](https://developer.wordpress.org/reference/functions/get_post/)`wp-includes/post.php` |

Retrieves post data given a post ID or post object.

  |

[Show 16 more](https://developer.wordpress.org/reference/functions/wp_playlist_shortcode/?output_format=md#)
[Show less](https://developer.wordpress.org/reference/functions/wp_playlist_shortcode/?output_format=md#)

## 󠀁[Changelog](https://developer.wordpress.org/reference/functions/wp_playlist_shortcode/?output_format=md#changelog)󠁿

| Version | Description | 
| [3.9.0](https://developer.wordpress.org/reference/since/3.9.0/) | Introduced. |

## 󠀁[User Contributed Notes](https://developer.wordpress.org/reference/functions/wp_playlist_shortcode/?output_format=md#user-contributed-notes)󠁿

 1.   [Skip to note 2 content](https://developer.wordpress.org/reference/functions/wp_playlist_shortcode/?output_format=md#comment-content-2291)
 2.    [David](https://profiles.wordpress.org/dmillerweb/)  [  9 years ago  ](https://developer.wordpress.org/reference/functions/wp_playlist_shortcode/#comment-2291)
 3.  [You must log in to vote on the helpfulness of this note](https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fwp_playlist_shortcode%2F%23comment-2291)
     Vote results for this note: 0[You must log in to vote on the helpfulness of this note](https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fwp_playlist_shortcode%2F%23comment-2291)
 4.  **FEEDBACK: **This (and other) code references would be quite a bit more useful
     if they could include SCREEN SHOTS of what the resulting page looks like, where
     applicable.
 5.  In this case, four screenshots of PLAYLIST results would be appropriate:
 6.   – type=”audio” style=”light” (default)
      – type=”audio” style=”dark” – type=”video”(
     style=”light” – default) – type=”video” style=”dark”
 7.  and other screenshots as needed to illustrate the results of various parameters.
 8.  NOTE: These would also be extremely useful on corresponding SHORTCODE pages of
     the codex.
 9.   [Log in to add feedback](https://login.wordpress.org/?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fwp_playlist_shortcode%2F%3Freplytocom%3D2291%23feedback-editor-2291)

You must [log in](https://login.wordpress.org/?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fwp_playlist_shortcode%2F)
before being able to contribute a note or feedback.