diff --git src/wp-includes/js/mce-view.js src/wp-includes/js/mce-view.js
index 1e8a1de..5caf801 100644
--- src/wp-includes/js/mce-view.js
+++ src/wp-includes/js/mce-view.js
@@ -451,10 +451,6 @@ window.wp = window.wp || {};
 				firefox = this.ua.is( 'ff' ),
 				className = '.wp-' +  this.shortcode.tag + '-shortcode';
 
-			if ( this.player ) {
-				this.unsetPlayer();
-			}
-
 			media = $( node ).find( className );
 
 			if ( ! this.isCompatible( media ) ) {
@@ -495,12 +491,7 @@ window.wp = window.wp || {};
 		},
 
 		unbind: function() {
-			var self = this;
-			this.pauseAllPlayers();
-			_.each( this.players, function (player) {
-				self.removePlayer( player );
-			} );
-			this.players = [];
+			this.unsetPlayers();
 		}
 	});
 	_.extend( wp.mce.media.View.prototype, wp.media.mixin );
@@ -547,22 +538,10 @@ window.wp = window.wp || {};
 		template:  media.template('editor-playlist'),
 
 		initialize: function( options ) {
+			this.players = [];
 			this.data = {};
 			this.attachments = [];
 			this.shortcode = options.shortcode;
-			_.bindAll( this, 'setPlayer' );
-			$(this).on('ready', this.setNode);
-		},
-
-		/**
-		 * Set the element context for the view, and then fetch the playlist's
-		 *   associated attachments.
-		 *
-		 * @param {Event} e
-		 * @param {HTMLElement} node
-		 */
-		setNode: function(e, node) {
-			this.node = node;
 			this.fetch();
 		},
 
@@ -571,7 +550,7 @@ window.wp = window.wp || {};
 		 */
 		fetch: function() {
 			this.attachments = wp.media.playlist.attachments( this.shortcode );
-			this.attachments.more().done( this.setPlayer );
+			this.dfd = this.attachments.more().done( _.bind( this.render, this ) );
 		},
 
 		/**
@@ -582,36 +561,31 @@ window.wp = window.wp || {};
 		 * @global WPPlaylistView
 		 * @global tinymce.editors
 		 */
-		setPlayer: function() {
-			var p,
-				html = this.getHtml(),
-				t = this.encodedText,
-				self = this;
-
-			this.unsetPlayer();
+		render: function() {
+			var html = this.getHtml(), self = this;
 
 			_.each( tinymce.editors, function( editor ) {
 				var doc;
 				if ( editor.plugins.wpview ) {
 					doc = editor.getDoc();
-					$( doc ).find( '[data-wpview-text="' + t + '"]' ).each(function(i, elem) {
+					$( doc ).find( '[data-wpview-text="' + this.encodedText + '"]' ).each(function (i, elem) {
 						var node = $( elem );
-						node.html( html );
-						self.node = elem;
-					});
-				}
-			}, this );
 
-			if ( ! this.data.tracks ) {
-				return;
-			}
+						// The <ins> is used to mark the end of the wrapper div. Needed when comparing
+						// the content as string for preventing extra undo levels.
+						node.html( html ).append( '<ins data-wpview-end="1"></ins>' );
 
-			p = new WPPlaylistView({
-				el: $( self.node ).find( '.wp-playlist' ).get(0),
-				metadata: this.data
-			});
+						if ( ! self.data.tracks ) {
+							return;
+						}
 
-			this.player = p.player;
+						self.players.push( new WPPlaylistView({
+							el: $( elem ).find( '.wp-playlist' ).get(0),
+							metadata: self.data
+						}).player );
+					});
+				}
+			}, this );
 		},
 
 		/**
@@ -695,6 +669,10 @@ window.wp = window.wp || {};
 			this.data = options;
 
 			return this.template( options );
+		},
+
+		unbind: function() {
+			this.unsetPlayers();
 		}
 	});
 	_.extend( wp.mce.media.PlaylistView.prototype, wp.media.mixin );
diff --git src/wp-includes/js/media-audiovideo.js src/wp-includes/js/media-audiovideo.js
index da91a9c..47f6d36 100644
--- src/wp-includes/js/media-audiovideo.js
+++ src/wp-includes/js/media-audiovideo.js
@@ -162,11 +162,13 @@
 		 *
 		 *  Examples: modal closes, shortcode properties are removed, etc.
 		 */
-		unsetPlayer : function() {
-			if ( this.player ) {
+		unsetPlayers : function() {
+			if ( this.players && this.players.length ) {
 				wp.media.mixin.pauseAllPlayers();
-				wp.media.mixin.removePlayer( this.player );
-				this.player = false;
+				_.each( this.players, function (player) {
+					wp.media.mixin.removePlayer( player );
+				} );
+				this.players = [];
 			}
 		}
 	};
@@ -705,10 +707,10 @@
 	media.view.MediaDetails = media.view.Settings.AttachmentDisplay.extend({
 		initialize: function() {
 			_.bindAll(this, 'success');
-
-			this.listenTo( this.controller, 'close', media.mixin.unsetPlayer );
+			this.players = [];
+			this.listenTo( this.controller, 'close', media.mixin.unsetPlayers );
 			this.on( 'ready', this.setPlayer );
-			this.on( 'media:setting:remove', media.mixin.unsetPlayer, this );
+			this.on( 'media:setting:remove', media.mixin.unsetPlayers, this );
 			this.on( 'media:setting:remove', this.render );
 			this.on( 'media:setting:remove', this.setPlayer );
 			this.events = _.extend( this.events, {
@@ -764,8 +766,8 @@
 		 * @global MediaElementPlayer
 		 */
 		setPlayer : function() {
-			if ( ! this.player && this.media ) {
-				this.player = new MediaElementPlayer( this.media, this.settings );
+			if ( ! this.players.length && this.media ) {
+				this.players.push( new MediaElementPlayer( this.media, this.settings ) );
 			}
 		},
 
diff --git src/wp-includes/media-template.php src/wp-includes/media-template.php
index 202fd07..a3300e5 100644
--- src/wp-includes/media-template.php
+++ src/wp-includes/media-template.php
@@ -16,7 +16,8 @@
 function wp_underscore_audio_template() {
 	$audio_types = wp_get_audio_extensions();
 ?>
-<audio controls
+<audio style="visibility: hidden"
+	controls
 	class="wp-audio-shortcode"
 	width="{{ _.isUndefined( data.model.width ) ? 400 : data.model.width }}"
 	preload="{{ _.isUndefined( data.model.preload ) ? 'none' : data.model.preload }}"
diff --git src/wp-includes/media.php src/wp-includes/media.php
index e9b4a1d..fe5b63b 100644
--- src/wp-includes/media.php
+++ src/wp-includes/media.php
@@ -1353,6 +1353,8 @@ function wp_playlist_shortcode( $attr ) {
 		echo (int) $theme_width;
 	?>"<?php if ( 'video' === $safe_type ):
 		echo ' height="', (int) $theme_height, '"';
+	else:
+		echo ' style="visibility: hidden"';
 	endif; ?>></<?php echo $safe_type ?>>
 	<div class="wp-playlist-next"></div>
 	<div class="wp-playlist-prev"></div>
@@ -1555,7 +1557,7 @@ function wp_audio_shortcode( $attr, $content = '' ) {
 		'loop'     => $loop,
 		'autoplay' => $autoplay,
 		'preload'  => $preload,
-		'style'    => 'width: 100%',
+		'style'    => 'width: 100%; visibility: hidden;',
 	);
 
 	// These ones should just be omitted altogether if they are blank
