Index: src/wp-includes/js/media-audiovideo.js
===================================================================
--- src/wp-includes/js/media-audiovideo.js	(revision 27653)
+++ src/wp-includes/js/media-audiovideo.js	(working copy)
@@ -1,8 +1,14 @@
 /* global _wpMediaViewsL10n, _wpmejsSettings, MediaElementPlayer, tinymce, WPPlaylistView */
 
-(function ($, _, Backbone) {
-	var media = wp.media, l10n = typeof _wpMediaViewsL10n === 'undefined' ? {} : _wpMediaViewsL10n;
+(function($, _, Backbone) {
+	var media = wp.media,
+		baseSettings = {},
+		l10n = typeof _wpMediaViewsL10n === 'undefined' ? {} : _wpMediaViewsL10n;
 
+	if ( ! _.isUndefined( window._wpmejsSettings ) ) {
+		baseSettings.pluginPath = _wpmejsSettings.pluginPath;
+	}
+
 	/**
 	 * @mixin
 	 */
@@ -11,7 +17,7 @@
 		/**
 		 * Pauses every instance of MediaElementPlayer
 		 */
-		pauseAllPlayers: function () {
+		pauseAllPlayers: function() {
 			var p;
 			if ( window.mejs && window.mejs.players ) {
 				for ( p in window.mejs.players ) {
@@ -24,7 +30,7 @@
 		 * Utility to identify the user's browser
 		 */
 		ua: {
-			is : function (browser) {
+			is : function( browser ) {
 				var passes = false, ua = window.navigator.userAgent;
 
 				switch ( browser ) {
@@ -44,7 +50,7 @@
 						passes = ua.match(/safari/gi) !== null && ua.match(/chrome/gi) === null;
 					break;
 					case 'chrome':
-						passes = ua.match(/safari/gi) && ua.match(/chrome/gi) !== null;
+						passes = ua.match(/safari/gi) !== null && ua.match(/chrome/gi) !== null;
 					break;
 				}
 
@@ -85,7 +91,7 @@
 		 * @param {jQuery} media
 		 * @returns {Boolean}
 		 */
-		isCompatible: function ( media ) {
+		isCompatible: function( media ) {
 			if ( ! media.find( 'source' ).length ) {
 				return false;
 			}
@@ -98,10 +104,10 @@
 
 			sources = media.find( 'source' );
 
-			_.find( this.compat, function (supports, browser) {
+			_.find( this.compat, function( supports, browser ) {
 				if ( ua.is( browser ) ) {
 					found = true;
-					_.each( sources, function (elem) {
+					_.each( sources, function( elem ) {
 						var audio = new RegExp( 'audio\/(' + supports.audio.join('|') + ')', 'gi' ),
 							video = new RegExp( 'video\/(' + supports.video.join('|') + ')', 'gi' );
 
@@ -214,21 +220,18 @@
 			caption : ''
 		},
 
-		edit : function (data) {
+		edit : function( data ) {
 			var frame, shortcode = wp.shortcode.next( 'audio', data ).shortcode;
 			frame = wp.media({
 				frame: 'audio',
 				state: 'audio-details',
-				metadata: _.defaults(
-					shortcode.attrs.named,
-					wp.media.audio.defaults
-				)
+				metadata: _.defaults( shortcode.attrs.named, this.defaults )
 			});
 
 			return frame;
 		},
 
-		shortcode : function (model) {
+		shortcode : function( model ) {
 			var self = this, content;
 
 			_.each( this.defaults, function( value, key ) {
@@ -268,12 +271,13 @@
 			autoplay : false,
 			preload : 'metadata',
 			content : '',
-			caption : ''
+			caption : '',
+			width : 640,
+			height : 360
 		},
 
-		edit : function (data) {
+		edit : function( data ) {
 			var frame,
-				defaults = this.defaults,
 				shortcode = wp.shortcode.next( 'video', data ).shortcode,
 				attrs;
 
@@ -283,13 +287,13 @@
 			frame = wp.media({
 				frame: 'video',
 				state: 'video-details',
-				metadata: _.defaults( attrs, defaults )
+				metadata: _.defaults( attrs, this.defaults )
 			});
 
 			return frame;
 		},
 
-		shortcode : function (model) {
+		shortcode : function( model ) {
 			var self = this, content;
 
 			_.each( this.defaults, function( value, key ) {
@@ -312,19 +316,20 @@
 	};
 
 	/**
-	 * wp.media.model.PostMedia
+	 * Shared model class for audio and video. Updates the model after
+	 *   "Add Audio|Video Source" and "Replace Audio|Video" states return
 	 *
 	 * @constructor
 	 * @augments Backbone.Model
-	 **/
+	 */
 	media.model.PostMedia = Backbone.Model.extend({
 		initialize: function() {
 			this.attachment = false;
 		},
 
-		setSource: function ( attachment ) {
+		setSource: function( attachment ) {
 			this.attachment = attachment;
-			this.extension = attachment.get('filename' ).split('.').pop();
+			this.extension = attachment.get( 'filename' ).split('.').pop();
 
 			if ( this.get( 'src' ) && this.extension === this.get( 'src' ).split('.').pop() ) {
 				this.unset( 'src' );
@@ -343,7 +348,7 @@
 			this.setSource( attachment );
 
 			this.unset( 'src' );
-			_.each( _.without( wp.media.view.settings.embedExts, this.extension ), function (ext) {
+			_.each( _.without( wp.media.view.settings.embedExts, this.extension ), function( ext ) {
 				self.unset( ext );
 			} );
 		}
@@ -350,7 +355,7 @@
 	});
 
 	/**
-	 * wp.media.controller.AudioDetails
+	 * The controller for the Audio Details state
 	 *
 	 * @constructor
 	 * @augments wp.media.controller.State
@@ -357,7 +362,7 @@
 	 * @augments Backbone.Model
 	 */
 	media.controller.AudioDetails = media.controller.State.extend({
-		defaults: _.defaults({
+		defaults: {
 			id: 'audio-details',
 			toolbar: 'audio-details',
 			title: l10n.audioDetailsTitle,
@@ -364,10 +369,8 @@
 			content: 'audio-details',
 			menu: 'audio-details',
 			router: false,
-			attachment: false,
-			priority: 60,
-			editing: false
-		}, media.controller.Library.prototype.defaults ),
+			priority: 60
+		},
 
 		initialize: function( options ) {
 			this.media = options.media;
@@ -376,7 +379,7 @@
 	});
 
 	/**
-	 * wp.media.controller.VideoDetails
+	 * The controller for the Video Details state
 	 *
 	 * @constructor
 	 * @augments wp.media.controller.State
@@ -383,7 +386,7 @@
 	 * @augments Backbone.Model
 	 */
 	media.controller.VideoDetails = media.controller.State.extend({
-		defaults: _.defaults({
+		defaults: {
 			id: 'video-details',
 			toolbar: 'video-details',
 			title: l10n.videoDetailsTitle,
@@ -390,10 +393,8 @@
 			content: 'video-details',
 			menu: 'video-details',
 			router: false,
-			attachment: false,
-			priority: 60,
-			editing: false
-		}, media.controller.Library.prototype.defaults ),
+			priority: 60
+		},
 
 		initialize: function( options ) {
 			this.media = options.media;
@@ -480,23 +481,17 @@
 
 		},
 
-		renderDetailsToolbar: function() {
+		setPrimaryButton: function(text, handler) {
 			this.toolbar.set( new media.view.Toolbar({
 				controller: this,
 				items: {
-					select: {
+					button: {
 						style:    'primary',
-						text:     l10n.update,
+						text:     text,
 						priority: 80,
-
-						click: function() {
-							var controller = this.controller,
-								state = controller.state();
-
-							controller.close();
-
-							state.trigger( 'update', controller.media.toJSON() );
-
+						click:    function() {
+							var controller = this.controller;
+							handler.call( this, controller, controller.state() );
 							// Restore and reset the default state.
 							controller.setState( controller.options.state );
 							controller.reset();
@@ -506,60 +501,27 @@
 			}) );
 		},
 
+		renderDetailsToolbar: function() {
+			this.setPrimaryButton( l10n.update, function( controller, state ) {
+				controller.close();
+				state.trigger( 'update', controller.media.toJSON() );
+			} );
+		},
+
 		renderReplaceToolbar: function() {
-			this.toolbar.set( new media.view.Toolbar({
-				controller: this,
-				items: {
-					replace: {
-						style:    'primary',
-						text:     l10n.replace,
-						priority: 80,
-
-						click: function() {
-							var controller = this.controller,
-								state = controller.state(),
-								selection = state.get( 'selection' ),
-								attachment = selection.single();
-
-							controller.media.changeAttachment( attachment );
-
-							state.trigger( 'replace', controller.media.toJSON() );
-
-							// Restore and reset the default state.
-							controller.setState( controller.options.state );
-							controller.reset();
-						}
-					}
-				}
-			}) );
+			this.setPrimaryButton( l10n.replace, function( controller, state ) {
+				var attachment = state.get( 'selection' ).single();
+				controller.media.changeAttachment( attachment );
+				state.trigger( 'replace', controller.media.toJSON() );
+			} );
 		},
 
 		renderAddSourceToolbar: function() {
-			this.toolbar.set( new media.view.Toolbar({
-				controller: this,
-				items: {
-					replace: {
-						style:    'primary',
-						text:     this.addText,
-						priority: 80,
-
-						click: function() {
-							var controller = this.controller,
-								state = controller.state(),
-								selection = state.get( 'selection' ),
-								attachment = selection.single();
-
-							controller.media.setSource( attachment );
-
-							state.trigger( 'add-source', controller.media.toJSON() );
-
-							// Restore and reset the default state.
-							controller.setState( controller.options.state );
-							controller.reset();
-						}
-					}
-				}
-			}) );
+			this.setPrimaryButton( this.addText, function( controller, state ) {
+				var attachment = state.get( 'selection' ).single();
+				controller.media.setSource( attachment );
+				state.trigger( 'add-source', controller.media.toJSON() );
+			} );
 		}
 	});
 
@@ -606,9 +568,7 @@
 		createStates: function() {
 			this.states.add([
 				new media.controller.AudioDetails( {
-					media: this.media,
-					editable: false,
-					menu: 'audio-details'
+					media: this.media
 				} ),
 
 				new media.controller.MediaLibrary( {
@@ -677,9 +637,7 @@
 		createStates: function() {
 			this.states.add([
 				new media.controller.VideoDetails({
-					media: this.media,
-					editable: false,
-					menu: 'video-details'
+					media: this.media
 				}),
 
 				new media.controller.MediaLibrary( {
@@ -721,68 +679,30 @@
 		},
 
 		renderSelectPosterImageToolbar: function() {
-			this.toolbar.set( new media.view.Toolbar({
-				controller: this,
-				items: {
-					replace: {
-						style:    'primary',
-						text:     l10n.videoSelectPosterImageTitle,
-						priority: 80,
+			this.setPrimaryButton( l10n.videoSelectPosterImageTitle, function( controller, state ) {
+				var attachment = state.get( 'selection' ).single();
 
-						click: function() {
-							var controller = this.controller,
-								state = controller.state(),
-								selection = state.get( 'selection' ),
-								attachment = selection.single();
-
-							controller.media.set( 'poster', attachment.get( 'url' ) );
-
-							state.trigger( 'set-poster-image', controller.media.toJSON() );
-
-							// Restore and reset the default state.
-							controller.setState( controller.options.state );
-							controller.reset();
-						}
-					}
-				}
-			}) );
+				controller.media.set( 'poster', attachment.get( 'url' ) );
+				state.trigger( 'set-poster-image', controller.media.toJSON() );
+			} );
 		},
 
 		renderAddTrackToolbar: function() {
-			this.toolbar.set( new media.view.Toolbar({
-				controller: this,
-				items: {
-					replace: {
-						style:    'primary',
-						text:     l10n.videoAddTrackTitle,
-						priority: 80,
+			this.setPrimaryButton( l10n.videoAddTrackTitle, function( controller, state ) {
+				var attachment = state.get( 'selection' ).single(),
+					content = controller.media.get( 'content' );
 
-						click: function() {
-							var controller = this.controller,
-								state = controller.state(),
-								selection = state.get( 'selection' ),
-								attachment = selection.single(),
-								content = controller.media.get( 'content' );
+				if ( -1 === content.indexOf( attachment.get( 'url' ) ) ) {
+					content += [
+						'<track srclang="en" label="English"kind="subtitles" src="',
+						attachment.get( 'url' ),
+						'" />'
+					].join('');
 
-							if ( -1 === content.indexOf( attachment.get( 'url' ) ) ) {
-								content += [
-									'<track srclang="en" label="English"kind="subtitles" src="',
-									attachment.get( 'url' ),
-									'" />'
-								].join('');
-
-								controller.media.set( 'content', content );
-							}
-
-							state.trigger( 'add-track', controller.media.toJSON() );
-
-							// Restore and reset the default state.
-							controller.setState( controller.options.state );
-							controller.reset();
-						}
-					}
+					controller.media.set( 'content', content );
 				}
-			}) );
+				state.trigger( 'add-track', controller.media.toJSON() );
+			} );
 		}
 	});
 
@@ -827,9 +747,8 @@
 		 *
 		 * @param {Event} e
 		 */
-		removeSetting : function (e) {
+		removeSetting : function(e) {
 			var wrap = $( e.currentTarget ).parent(), setting;
-
 			setting = wrap.find( 'input' ).data( 'setting' );
 
 			if ( setting ) {
@@ -844,10 +763,10 @@
 		 *
 		 * @fires wp.media.view.MediaDetails#media:setting:remove
 		 */
-		setTracks : function () {
+		setTracks : function() {
 			var tracks = '';
 
-			_.each( this.$('.content-track'), function (track) {
+			_.each( this.$('.content-track'), function(track) {
 				tracks += $( track ).val();
 			} );
 
@@ -858,7 +777,7 @@
 		/**
 		 * @global MediaElementPlayer
 		 */
-		setPlayer : function () {
+		setPlayer : function() {
 			if ( ! this.player && this.media ) {
 				this.player = new MediaElementPlayer( this.media, this.settings );
 			}
@@ -867,15 +786,15 @@
 		/**
 		 * @abstract
 		 */
-		setMedia : function () {
+		setMedia : function() {
 			return this;
 		},
 
-		success : function (mejs) {
+		success : function(mejs) {
 			var autoplay = mejs.attributes.autoplay && 'false' !== mejs.attributes.autoplay;
 
 			if ( 'flash' === mejs.pluginType && autoplay ) {
-				mejs.addEventListener( 'canplay', function () {
+				mejs.addEventListener( 'canplay', function() {
 					mejs.play();
 				}, false );
 			}
@@ -884,23 +803,17 @@
 		},
 
 		/**
-		 * @global _wpmejsSettings
-		 *
 		 * @returns {media.view.MediaDetails} Returns itself to allow chaining
 		 */
 		render: function() {
-			var self = this, settings = {
-				success : this.success
-			};
+			var self = this;
 
-			if ( ! _.isUndefined( window._wpmejsSettings ) ) {
-				settings.pluginPath = _wpmejsSettings.pluginPath;
-			}
-
 			media.view.Settings.AttachmentDisplay.prototype.render.apply( this, arguments );
 			setTimeout( function() { self.resetFocus(); }, 10 );
 
-			this.settings = settings;
+			this.settings = _.defaults( {
+				success : this.success
+			}, baseSettings );
 
 			return this.setMedia();
 		},
@@ -914,12 +827,12 @@
 		/**
 		 * When multiple players in the DOM contain the same src, things get weird.
 		 *
-		 * @param {HTMLElement} media
+		 * @param {HTMLElement} elem
 		 * @returns {HTMLElement}
 		 */
-		prepareSrc : function (media) {
-			var i = wp.media.view.MediaDetails.instances++;
-			_.each( $(media).find('source'), function (source) {
+		prepareSrc : function( elem ) {
+			var i = media.view.MediaDetails.instances++;
+			_.each( $( elem ).find( 'source' ), function( source ) {
 				source.src = [
 					source.src,
 					source.src.indexOf('?') > -1 ? '&' : '?',
@@ -926,9 +839,9 @@
 					'_=',
 					i
 				].join('');
-			});
+			} );
 
-			return media;
+			return elem;
 		}
 	});
 
@@ -1010,16 +923,16 @@
 		 * @param {Object} settings
 		 * @returns {Object}
 		 */
-		counts : (function (settings) {
+		counts : (function(settings) {
 			var counts = {};
 
-			return  function () {
+			return  function() {
 				if ( ! _.isEmpty( counts ) ) {
 					return counts;
 				}
 
 				var a = 0, v = 0;
-				_.each( settings.attachmentCounts, function (total, mime) {
+				_.each( settings.attachmentCounts, function(total, mime) {
 					var type;
 					if ( -1 < mime.indexOf('/') ) {
 						type = mime.split('/')[0];
@@ -1050,7 +963,7 @@
 		 * @param {Object} options
 		 * @returns {Array}
 		 */
-		states : function (options) {
+		states : function(options) {
 			return [
 				new media.controller.Library({
 					id:         'playlist',
@@ -1093,7 +1006,7 @@
 		 * @param {Object} options
 		 * @returns {Array}
 		 */
-		videoStates : function (options) {
+		videoStates : function(options) {
 			return [
 				new media.controller.Library({
 					id:         'video-playlist',
@@ -1183,7 +1096,7 @@
 
 			data = window.decodeURIComponent( $( node ).attr('data-wpview-text') );
 			frame = media.edit( data );
-			frame.on( 'close', function () {
+			frame.on( 'close', function() {
 				frame.detach();
 			} );
 			frame.state( self.state ).on( 'update', function( selection ) {
@@ -1219,7 +1132,7 @@
 		 * @param {Event} e
 		 * @param {HTMLElement} node
 		 */
-		setPlayer: function (e, node) {
+		setPlayer: function(e, node) {
 			// if the ready event fires on an empty node
 			if ( ! node ) {
 				return;
@@ -1227,7 +1140,7 @@
 
 			var self = this,
 				media,
-				settings = {},
+				firefox = this.ua.is( 'ff' ),
 				className = '.wp-' +  this.shortcode.tag + '-shortcode';
 
 			if ( this.player ) {
@@ -1236,10 +1149,6 @@
 
 			media = $( node ).find( className );
 
-			if ( ! _.isUndefined( window._wpmejsSettings ) ) {
-				settings.pluginPath = _wpmejsSettings.pluginPath;
-			}
-
 			if ( ! this.isCompatible( media ) ) {
 				media.closest( '.wpview-wrap' ).addClass( 'wont-play' );
 				if ( ! media.parent().hasClass( 'wpview-wrap' ) ) {
@@ -1249,7 +1158,7 @@
 				return;
 			} else {
 				media.closest( '.wpview-wrap' ).removeClass( 'wont-play' );
-				if ( this.ua.is( 'ff' ) ) {
+				if ( firefox ) {
 					media.prop( 'preload', 'metadata' );
 				} else {
 					media.prop( 'preload', 'none' );
@@ -1259,9 +1168,13 @@
 			media = wp.media.view.MediaDetails.prepareSrc( media.get(0) );
 
 			// Thanks, Firefox!
-			setTimeout(function () {
-				self.player = new MediaElementPlayer( media, settings );
-			}, 50);
+			if ( firefox ) {
+				setTimeout( function() {
+					self.player = new MediaElementPlayer( media, baseSettings );
+				}, 50 );
+			} else {
+				this.player = new MediaElementPlayer( media, baseSettings );
+			}
 		},
 
 		/**
@@ -1270,7 +1183,10 @@
 		 * @returns {string}
 		 */
 		getHtml: function() {
-			var attrs = this.shortcode.attrs.named;
+			var attrs = _.defaults(
+				this.shortcode.attrs.named,
+				wp.media[ this.shortcode.tag ].defaults
+			);
 			return this.template({ model: attrs });
 		}
 	});
@@ -1332,7 +1248,7 @@
 		 * @param {Event} e
 		 * @param {HTMLElement} node
 		 */
-		setNode: function (e, node) {
+		setNode: function(e, node) {
 			this.node = node;
 			this.fetch();
 		},
@@ -1353,7 +1269,7 @@
 		 * @global WPPlaylistView
 		 * @global tinymce.editors
 		 */
-		setPlayer: function () {
+		setPlayer: function() {
 			var p,
 				html = this.getHtml(),
 				t = this.encodedText,
@@ -1365,7 +1281,7 @@
 				var doc;
 				if ( editor.plugins.wpview ) {
 					doc = editor.getDoc();
-					$( doc ).find( '[data-wpview-text="' + t + '"]' ).each(function (i, elem) {
+					$( doc ).find( '[data-wpview-text="' + t + '"]' ).each(function(i, elem) {
 						var node = $( elem );
 						node.html( html );
 						self.node = elem;
@@ -1414,8 +1330,8 @@
 				artists: data.artists
 			};
 
-			_.each( attachments, function (attachment) {
-				var size = {}, track = {
+			_.each( attachments, function( attachment ) {
+				var size = {}, resize = {}, track = {
 					src : attachment.url,
 					type : attachment.mime,
 					title : attachment.title,
@@ -1425,15 +1341,24 @@
 				};
 
 				if ( 'video' === type ) {
-					if ( ! options.width ) {
-						options.width = attachment.width;
-						options.height = attachment.height;
-					}
 					size.width = attachment.width;
 					size.height = attachment.height;
+					if ( media.view.settings.contentWidth ) {
+						resize.width = media.view.settings.contentWidth - 22;
+						resize.height = Math.ceil( ( size.height * resize.width ) / size.width );
+						if ( ! options.width ) {
+							options.width = resize.width;
+							options.height = resize.height;
+						}
+					} else {
+						if ( ! options.width ) {
+							options.width = attachment.width;
+							options.height = attachment.height;
+						}
+					}
 					track.dimensions = {
 						original : size,
-						resized : size
+						resized : _.isEmpty( resize ) ? size : resize
 					};
 				} else {
 					options.width = 400;
@@ -1483,7 +1408,7 @@
 	function init() {
 		$(document.body)
 			.on( 'click', '.wp-switch-editor', wp.media.mixin.pauseAllPlayers )
-			.on( 'click', '.add-media-source', function () {
+			.on( 'click', '.add-media-source', function() {
 				media.frame.setState('add-' + media.frame.defaults.id + '-source');
 			} );
 	}
Index: src/wp-includes/js/tinymce/skins/wordpress/wp-content.css
===================================================================
--- src/wp-includes/js/tinymce/skins/wordpress/wp-content.css	(revision 27653)
+++ src/wp-includes/js/tinymce/skins/wordpress/wp-content.css	(working copy)
@@ -164,6 +164,10 @@
 	max-width: 100%;
 }
 
+audio {
+	visibility: hidden;
+}
+
 /**
  * WP Views
  */
Index: src/wp-includes/media-template.php
===================================================================
--- src/wp-includes/media-template.php	(revision 27653)
+++ src/wp-includes/media-template.php	(working copy)
@@ -48,14 +48,20 @@
 function wp_underscore_video_template() {
 	$video_types = wp_get_video_extensions();
 ?>
-<#
-var isYouTube = ! _.isEmpty( data.model.src ) && data.model.src.match(/youtube|youtu\.be/);
-	w = ! data.model.width || data.model.width > 640 ? 640 : data.model.width,
-	h = ! data.model.height ? 360 : data.model.height;
+<#  var w, h, settings = wp.media.view.settings,
+		isYouTube = ! _.isEmpty( data.model.src ) && data.model.src.match(/youtube|youtu\.be/);
 
-if ( data.model.width && w !== data.model.width ) {
-	h = Math.ceil( ( h * w ) / data.model.width );
-}
+	if ( settings.contentWidth && data.model.width >= settings.contentWidth ) {
+		w = settings.contentWidth;
+	} else {
+		w = data.model.width;
+	}
+
+	if ( w !== data.model.width ) {
+		h = Math.ceil( ( h * w ) / data.model.width );
+	} else {
+		h = data.model.height;
+	}
 #>
 <div style="max-width: 100%; width: {{ w }}px">
 <video controls
@@ -85,13 +91,13 @@
 		if ( isYouTube ) { #>
 		<source src="{{ data.model.src }}" type="video/youtube" />
 		<# } else { #>
-		<source src="{{ data.model.src }}" type="{{ wp.media.view.settings.embedMimes[ data.model.src.split('.').pop() ] }}" />
+		<source src="{{ data.model.src }}" type="{{ settings.embedMimes[ data.model.src.split('.').pop() ] }}" />
 		<# }
 	} #>
 
 	<?php foreach ( $video_types as $type ):
 	?><# if ( data.model.<?php echo $type ?> ) { #>
-	<source src="{{ data.model.<?php echo $type ?> }}" type="{{ wp.media.view.settings.embedMimes[ '<?php echo $type ?>' ] }}" />
+	<source src="{{ data.model.<?php echo $type ?> }}" type="{{ settings.embedMimes[ '<?php echo $type ?>' ] }}" />
 	<# } #>
 	<?php endforeach; ?>
 	{{{ data.model.content }}}
Index: src/wp-includes/media.php
===================================================================
--- src/wp-includes/media.php	(revision 27653)
+++ src/wp-includes/media.php	(working copy)
@@ -1197,8 +1197,8 @@
 	$default_width = 640;
 	$default_height = 360;
 
-	$theme_width = $content_width - $outer;
-	$theme_height = round( ( $default_height * $theme_width ) / $default_width );
+	$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 = compact( 'type', 'style' );
 
@@ -1585,7 +1585,7 @@
 		}
 	} else {
 		// if the video is bigger than the theme
-		if ( $width > $content_width ) {
+		if ( ! empty( $content_width ) && $width > $content_width ) {
 			$height = round( ( $height * $content_width ) / $width );
 			$width = $content_width;
 		}
@@ -2381,6 +2381,8 @@
 	if ( did_action( 'wp_enqueue_media' ) )
 		return;
 
+	global $content_width;
+
 	$defaults = array(
 		'post' => null,
 	);
@@ -2431,7 +2433,8 @@
 		'defaultProps' => $props,
 		'attachmentCounts' => wp_count_attachments(),
 		'embedExts'    => $exts,
-		'embedMimes'   => $ext_mimes
+		'embedMimes'   => $ext_mimes,
+		'contentWidth' => $content_width,
 	);
 
 	$post = null;
