diff --git wp-includes/media.php wp-includes/media.php
index 9b5d6a8..f5c0d68 100644
--- wp-includes/media.php
+++ wp-includes/media.php
@@ -839,41 +839,46 @@ function wp_get_audio_extensions() {
 /**
  * The Audio shortcode.
  *
  * This implements the functionality of the Audio Shortcode for displaying
  * WordPress mp3s in a post.
  *
  * @since 3.6.0
  *
  * @param array $attr Attributes of the shortcode.
  * @return string HTML content to display audio.
  */
 function wp_audio_shortcode( $attr ) {
 	$post_id = get_post() ? get_the_ID() : 0;
 
 	static $instances = 0;
 	$instances++;
 
 	$audio = null;
 
 	$default_types = wp_get_audio_extensions();
-	$defaults_atts = array( 'src' => '' );
+	$defaults_atts = array(
+		'src'      => '',
+		'loop'     => '',
+		'autoplay' => '',
+		'preload' => 'none'
+	);
 	foreach ( $default_types as $type )
 		$defaults_atts[$type] = '';
 
 	$atts = shortcode_atts( $defaults_atts, $attr, 'audio' );
 	extract( $atts );
 
 	$primary = false;
 	if ( ! empty( $src ) ) {
 		$type = wp_check_filetype( $src );
 		if ( ! in_array( $type['ext'], $default_types ) )
 			return sprintf( '<a class="wp-post-format-link-audio" href="%s">%s</a>', esc_url( $src ), esc_html( $src ) );
 		$primary = true;
 		array_unshift( $default_types, 'src' );
 	} else {
 		foreach ( $default_types as $ext ) {
 			if ( ! empty( $$ext ) ) {
 				$type = wp_check_filetype( $$ext );
 				if ( $type['ext'] === $ext )
 					$primary = true;
 			}
@@ -883,45 +888,59 @@ function wp_audio_shortcode( $attr ) {
 	if ( ! $primary ) {
 		$audios = get_attached_media( 'audio', $post_id );
 		if ( empty( $audios ) )
 			return;
 
 		$audio = reset( $audios );
 		$src = wp_get_attachment_url( $audio->ID );
 		if ( empty( $src ) )
 			return;
 
 		array_unshift( $default_types, 'src' );
 	}
 
 	$library = apply_filters( 'wp_audio_shortcode_library', 'mediaelement' );
 	if ( 'mediaelement' === $library && did_action( 'init' ) ) {
 		wp_enqueue_style( 'wp-mediaelement' );
 		wp_enqueue_script( 'wp-mediaelement' );
 	}
 
 	$atts = array(
-		sprintf( 'class="%s"', apply_filters( 'wp_audio_shortcode_class', 'wp-audio-shortcode' ) ),
-		sprintf( 'id="audio-%d-%d"', $post_id, $instances ),
+		'class'    => apply_filters( 'wp_audio_shortcode_class', 'wp-audio-shortcode' ),
+		'id'       => sprintf( 'audio-%d-%d', $post_id, $instances ),
+		'loop'     => $loop,
+		'autoplay' => $autoplay,
+		'preload'  => $preload,
 	);
 
-	$html = sprintf( '<audio %s controls="controls" preload="none">', join( ' ', $atts ) );
+	// These ones should just be omitted altogether if they are blank
+	foreach ( array( 'loop', 'autoplay', 'preload' ) as $a ) {
+		if ( empty( $atts[$a] ) )
+			unset( $atts[$a] );
+	}
+
+	$attr_strings = [];
+	foreach ( $atts as $k => $v ) {
+		$attr_strings[] = $k . '="' . esc_attr( $v ) . '"';
+	}
+
+	$html = sprintf( '<audio %s controls="controls">', join( ' ', $attr_strings ) );
 
 	$fileurl = '';
 	$source = '<source type="%s" src="%s" />';
 	foreach ( $default_types as $fallback ) {
 		if ( ! empty( $$fallback ) ) {
 			if ( empty( $fileurl ) )
 				$fileurl = $$fallback;
 			$type = wp_check_filetype( $$fallback );
 			$html .= sprintf( $source, $type['type'], esc_url( $$fallback ) );
 		}
 	}
 
 	if ( 'mediaelement' === $library )
 		$html .= wp_mediaelement_fallback( $fileurl );
 	$html .= '</audio>';
 
 	return apply_filters( 'wp_audio_shortcode', $html, $atts, $audio, $post_id );
 }
 add_shortcode( 'audio', apply_filters( 'wp_audio_shortcode_handler', 'wp_audio_shortcode' ) );
 
@@ -940,44 +959,47 @@ function wp_get_video_extensions() {
  *
  * This implements the functionality of the Video Shortcode for displaying
  * WordPress mp4s in a post.
  *
  * @since 3.6.0
  *
  * @param array $attr Attributes of the shortcode.
  * @return string HTML content to display video.
  */
 function wp_video_shortcode( $attr ) {
 	global $content_width;
 	$post_id = get_post() ? get_the_ID() : 0;
 
 	static $instances = 0;
 	$instances++;
 
 	$video = null;
 
 	$default_types = wp_get_video_extensions();
 	$defaults_atts = array(
-		'src' => '',
-		'poster' => '',
-		'height' => 360,
-		'width' => empty( $content_width ) ? 640 : $content_width,
+		'src'      => '',
+		'poster'   => '',
+		'loop'     => '',
+		'autoplay' => '',
+		'preload'  => 'metadata',
+		'height'   => 360,
+		'width'    => empty( $content_width ) ? 640 : $content_width,
 	);
 
 	foreach ( $default_types as $type )
 		$defaults_atts[$type] = '';
 
 	$atts = shortcode_atts( $defaults_atts, $attr, 'video' );
 	extract( $atts );
 
 	$w = $width;
 	$h = $height;
 	if ( is_admin() && $width > 600 )
 		$w = 600;
 	elseif ( ! is_admin() && $w > $defaults_atts['width'] )
 		$w = $defaults_atts['width'];
 
 	if ( $w < $width )
 		$height = round( ( $h * $w ) / $width );
 
 	$width = $w;
 
@@ -1001,68 +1023,81 @@ function wp_video_shortcode( $attr ) {
 	if ( ! $primary ) {
 		$videos = get_attached_media( 'video', $post_id );
 		if ( empty( $videos ) )
 			return;
 
 		$video = reset( $videos );
 		$src = wp_get_attachment_url( $video->ID );
 		if ( empty( $src ) )
 			return;
 
 		array_unshift( $default_types, 'src' );
 	}
 
 	$library = apply_filters( 'wp_video_shortcode_library', 'mediaelement' );
 	if ( 'mediaelement' === $library && did_action( 'init' ) ) {
 		wp_enqueue_style( 'wp-mediaelement' );
 		wp_enqueue_script( 'wp-mediaelement' );
 	}
 
 	$atts = array(
-		sprintf( 'class="%s"', apply_filters( 'wp_video_shortcode_class', 'wp-video-shortcode' ) ),
-		sprintf( 'id="video-%d-%d"', $post_id, $instances ),
-		sprintf( 'width="%d"', $width ),
-		sprintf( 'height="%d"', $height ),
+		'class'    => apply_filters( 'wp_video_shortcode_class', 'wp-video-shortcode' ),
+		'id'       => sprintf( 'video-%d-%d', $post_id, $instances ),
+		'width'    => absint( $width ),
+		'height'   => absint( $height ),
+		'poster'   => esc_url( $poster ),
+		'loop'     => $loop,
+		'autoplay' => $autoplay,
+		'preload'  => $preload,
 	);
 
-	if ( ! empty( $poster ) )
-		$atts[] = sprintf( 'poster="%s"', esc_url( $poster ) );
+	// These ones should just be omitted altogether if they are blank
+	foreach ( array( 'poster', 'loop', 'autoplay', 'preload' ) as $a ) {
+		if ( empty( $atts[$a] ) )
+			unset( $atts[$a] );
+	}
+
+	$attr_strings = [];
+	foreach ( $atts as $k => $v ) {
+		$attr_strings[] = $k . '="' . esc_attr( $v ) . '"';
+	}
 
-	$html = sprintf( '<video %s controls="controls" preload="none">', join( ' ', $atts ) );
+	$html = sprintf( '<video %s controls="controls">', join( ' ', $attr_strings ) );
 
 	$fileurl = '';
 	$source = '<source type="%s" src="%s" />';
 	foreach ( $default_types as $fallback ) {
 		if ( ! empty( $$fallback ) ) {
 			if ( empty( $fileurl ) )
 				$fileurl = $$fallback;
 			$type = wp_check_filetype( $$fallback );
 			// m4v sometimes shows up as video/mpeg which collides with mp4
 			if ( 'm4v' === $type['ext'] )
 				$type['type'] = 'video/m4v';
 			$html .= sprintf( $source, $type['type'], esc_url( $$fallback ) );
 		}
 	}
 	if ( 'mediaelement' === $library )
 		$html .= wp_mediaelement_fallback( $fileurl );
 	$html .= '</video>';
 
+	$html = sprintf( '<div style="width: %dpx; max-width: 100%%;">%s</div>', $width, $html );
 	return apply_filters( 'wp_video_shortcode', $html, $atts, $video, $post_id );
 }
 add_shortcode( 'video', apply_filters( 'wp_video_shortcode_handler', 'wp_video_shortcode' ) );
 
 /**
  * Display previous image link that has the same post parent.
  *
  * @since 2.5.0
  * @param string $size Optional, default is 'thumbnail'. Size of image, either array or string. 0 or 'none' will default to post_title or $text;
  * @param string $text Optional, default is false. If included, link will reflect $text variable.
  * @return string HTML content.
  */
 function previous_image_link($size = 'thumbnail', $text = false) {
 	adjacent_image_link(true, $size, $text);
 }
 
 /**
  * Display next image link that has the same post parent.
  *
  * @since 2.5.0
