Index: src/wp-admin/css/customize-controls.css
===================================================================
--- src/wp-admin/css/customize-controls.css	(revision 31694)
+++ src/wp-admin/css/customize-controls.css	(working copy)
@@ -582,8 +582,9 @@
 	-webkit-overflow-scrolling: touch;
 }
 
-/** Header control **/
+/** Media controls **/
 
+.customize-control-media .current,
 .customize-control-upload .current,
 .customize-control-image .current,
 .customize-control-background .current,
@@ -610,6 +611,9 @@
 	display: block;
 }
 
+.customize-control-media .remove-button,
+.customize-control-media .default-button,
+.customize-control-media .upload-button,
 .customize-control-upload .remove-button,
 .customize-control-upload .default-button,
 .customize-control-upload .upload-button,
@@ -626,6 +630,7 @@
 	height: auto;
 }
 
+.customize-control-media .current .container,
 .customize-control-upload .current .container,
 .customize-control-image .current .container,
 .customize-control-background .current .container,
@@ -637,12 +642,14 @@
 	border-radius: 2px;
 }
 
+.customize-control-media .current .container,
 .customize-control-upload .current .container,
 .customize-control-background .current .container,
 .customize-control-image .current .container {
 	min-height: 40px;
 }
 
+.customize-control-media .placeholder,
 .customize-control-upload .placeholder,
 .customize-control-image .placeholder,
 .customize-control-background .placeholder,
@@ -653,6 +660,7 @@
 	cursor: default;
 }
 
+.customize-control-media .inner,
 .customize-control-upload .inner,
 .customize-control-image .inner,
 .customize-control-background .inner,
@@ -666,6 +674,7 @@
 	overflow: hidden;
 }
 
+.customize-control-media .inner,
 .customize-control-upload .inner,
 .customize-control-background .inner,
 .customize-control-image .inner {
@@ -673,6 +682,7 @@
 	min-height: 40px;
 }
 
+.customize-control-media .inner,
 .customize-control-upload .inner,
 .customize-control-image .inner,
 .customize-control-background .inner,
@@ -782,6 +792,7 @@
 	100% { color: #d4b146; }
 }
 
+.customize-control-media .actions,
 .customize-control-upload .actions,
 .customize-control-image .actions,
 .customize-control-background .actions,
@@ -799,6 +810,7 @@
 	margin-bottom: 0;
 }
 
+.customize-control-media img,
 .customize-control-upload img,
 .customize-control-image img,
 .customize-control-background img,
@@ -808,6 +820,8 @@
 	border-radius: 2px;
 }
 
+.customize-control-media .remove-button,
+.customize-control-media .default-button,
 .customize-control-upload .remove-button,
 .customize-control-upload .default-button,
 .customize-control-image .remove-button,
@@ -819,6 +833,7 @@
 	margin-right: 3px;
 }
 
+.customize-control-media .upload-button,
 .customize-control-upload .upload-button,
 .customize-control-image .upload-button,
 .customize-control-background .upload-button,
Index: src/wp-admin/js/customize-controls.js
===================================================================
--- src/wp-admin/js/customize-controls.js	(revision 31697)
+++ src/wp-admin/js/customize-controls.js	(working copy)
@@ -1370,13 +1370,13 @@
 	});
 
 	/**
-	 * An upload control, which utilizes the media modal.
+	 * A control that implements the media modal.
 	 *
 	 * @class
 	 * @augments wp.customize.Control
 	 * @augments wp.customize.Class
 	 */
-	api.UploadControl = api.Control.extend({
+	api.MediaControl = api.Control.extend({
 
 		/**
 		 * When the control's DOM structure is ready,
@@ -1471,7 +1471,7 @@
 			this.params.attachment = attachment;
 
 			// Set the Customizer setting; the callback takes care of rendering.
-			this.setting( attachment.url );
+			this.setting( attachment.id );
 			node = this.container.find( 'audio, video' ).get(0);
 
 			// Initialize audio/video previews.
@@ -1509,6 +1509,41 @@
 			this.params.attachment = {};
 			this.setting( '' );
 			this.renderContent(); // Not bound to setting change when emptying.
+		}
+	});
+
+	/**
+	 * An upload control, which utilizes the media modal.
+	 *
+	 * @class
+	 * @augments wp.customize.MediaControl
+	 * @augments wp.customize.Control
+	 * @augments wp.customize.Class
+	 */
+	api.UploadControl = api.MediaControl.extend({
+
+		/**
+		 * Callback handler for when an attachment is selected in the media modal.
+		 * Gets the selected image information, and sets it within the control.
+		 */
+		select: function() {
+			// Get the attachment from the modal frame.
+			var node,
+				attachment = this.frame.state().get( 'selection' ).first().toJSON(),
+				mejsSettings = window._wpmejsSettings || {};
+
+			this.params.attachment = attachment;
+
+			// Set the Customizer setting; the callback takes care of rendering.
+			this.setting( attachment.url );
+			node = this.container.find( 'audio, video' ).get(0);
+
+			// Initialize audio/video previews.
+			if ( node ) {
+				this.player = new MediaElementPlayer( node, mejsSettings );
+			} else {
+				this.cleanupPlayer();
+			}
 		},
 
 		// @deprecated
@@ -1526,6 +1561,7 @@
 	 *
 	 * @class
 	 * @augments wp.customize.UploadControl
+	 * @augments wp.customize.MediaControl
 	 * @augments wp.customize.Control
 	 * @augments wp.customize.Class
 	 */
@@ -1539,6 +1575,7 @@
 	 *
 	 * @class
 	 * @augments wp.customize.UploadControl
+	 * @augments wp.customize.MediaControl
 	 * @augments wp.customize.Control
 	 * @augments wp.customize.Class
 	 */
@@ -1575,8 +1612,8 @@
 	 */
 	api.HeaderControl = api.Control.extend({
 		ready: function() {
-			this.btnRemove        = $('#customize-control-header_image .actions .remove');
-			this.btnNew           = $('#customize-control-header_image .actions .new');
+			this.btnRemove = $('#customize-control-header_image .actions .remove');
+			this.btnNew    = $('#customize-control-header_image .actions .new');
 
 			_.bindAll(this, 'openMedia', 'removeImage');
 
@@ -2311,6 +2348,7 @@
 
 	api.controlConstructor = {
 		color:      api.ColorControl,
+		media:      api.MediaControl,
 		upload:     api.UploadControl,
 		image:      api.ImageControl,
 		header:     api.HeaderControl,
Index: src/wp-includes/class-wp-customize-control.php
===================================================================
--- src/wp-includes/class-wp-customize-control.php	(revision 31694)
+++ src/wp-includes/class-wp-customize-control.php	(working copy)
@@ -521,11 +521,11 @@
 	 * @since 4.1.0
 	 */
 	final public function print_template() {
-	        ?>
-	        <script type="text/html" id="tmpl-customize-control-<?php echo $this->type; ?>-content">
-	                <?php $this->content_template(); ?>
-	        </script>
-	        <?php
+		?>
+		<script type="text/html" id="tmpl-customize-control-<?php echo $this->type; ?>-content">
+			<?php $this->content_template(); ?>
+		</script>
+		<?php
 	}
 
 	/**
@@ -638,24 +638,22 @@
 }
 
 /**
- * Customize Upload Control class.
+ * Customize Media Control class.
  *
- * @since 3.4.0
+ * @since 4.2.0
  *
  * @see WP_Customize_Control
  */
-class WP_Customize_Upload_Control extends WP_Customize_Control {
-	public $type          = 'upload';
+class WP_Customize_Media_Control extends WP_Customize_Control {
+	public $type          = 'media';
 	public $mime_type     = '';
 	public $button_labels = array();
-	public $removed = ''; // unused
-	public $context; // unused
-	public $extensions = array(); // unused
 
 	/**
 	 * Constructor.
 	 *
 	 * @since 4.1.0
+	 * @since 4.2.0 Moved from WP_Customize_Upload_Control.
 	 *
 	 * @param WP_Customize_Manager $manager {@see WP_Customize_Manager} instance.
 	 */
@@ -677,6 +675,7 @@
 	 * Enqueue control related scripts/styles.
 	 *
 	 * @since 3.4.0
+	 * @since 4.2.0 Moved from WP_Customize_Upload_Control.
 	 */
 	public function enqueue() {
 		wp_enqueue_media();
@@ -686,6 +685,8 @@
 	 * Refresh the parameters passed to the JavaScript via JSON.
 	 *
 	 * @since 3.4.0
+	 * @since 4.2.0 Moved from WP_Customize_Upload_Control.
+	 *
 	 * @uses WP_Customize_Control::to_json()
 	 */
 	public function to_json() {
@@ -698,6 +699,7 @@
 		if ( is_object( $this->setting ) ) {
 			if ( $this->setting->default ) {
 				// Fake an attachment model - needs all fields used by template.
+				// Note that the default value must be a URL, NOT an attachment ID.
 				$type = in_array( substr( $this->setting->default, -3 ), array( 'jpg', 'png', 'gif', 'bmp' ) ) ? 'image' : 'document';
 				$default_attachment = array(
 					'id' => 1,
@@ -720,11 +722,7 @@
 				// Set the default as the attachment.
 				$this->json['attachment'] = $this->json['defaultAttachment'];
 			} elseif ( $value ) {
-				// Get the attachment model for the existing file.
-				$attachment_id = attachment_url_to_postid( $value );
-				if ( $attachment_id ) {
-					$this->json['attachment'] = wp_prepare_attachment_for_js( $attachment_id );
-				}
+				$this->json['attachment'] = wp_prepare_attachment_for_js( $value );
 			}
 		}
 	}
@@ -732,15 +730,18 @@
 	/**
 	 * Don't render any content for this control from PHP.
 	 *
-	 * @see WP_Customize_Upload_Control::content_template()
 	 * @since 3.4.0
+	 * @since 4.2.0 Moved from WP_Customize_Upload_Control.
+	 *
+	 * @see WP_Customize_Media_Control::content_template()
 	 */
 	public function render_content() {}
 
 	/**
-	 * Render a JS template for the content of the upload control.
+	 * Render a JS template for the content of the media control.
 	 *
 	 * @since 4.1.0
+	 * @since 4.2.0 Moved from WP_Customize_Upload_Control.
 	 */
 	public function content_template() {
 		?>
@@ -823,6 +824,42 @@
 }
 
 /**
+ * Customize Upload Control Class.
+ *
+ * @since 3.4.0
+ *
+ * @see WP_Customize_Media_Control
+ */
+class WP_Customize_Upload_Control extends WP_Customize_Media_Control {
+	public $type          = 'upload';
+	public $mime_type     = '';
+	public $button_labels = array();
+	public $removed = ''; // unused
+	public $context; // unused
+	public $extensions = array(); // unused
+
+	/**
+	 * Refresh the parameters passed to the JavaScript via JSON.
+	 *
+	 * @since 3.4.0
+	 *
+	 * @uses WP_Customize_Media_Control::to_json()
+	 */
+	public function to_json() {
+		parent::to_json();
+
+		$value = $this->value();
+		if ( $value ) {
+			// Get the attachment model for the existing file.
+			$attachment_id = attachment_url_to_postid( $value );
+			if ( $attachment_id ) {
+				$this->json['attachment'] = wp_prepare_attachment_for_js( $attachment_id );
+			}
+		}
+	}
+}
+
+/**
  * Customize Image Control class.
  *
  * @since 3.4.0
Index: src/wp-includes/class-wp-customize-manager.php
===================================================================
--- src/wp-includes/class-wp-customize-manager.php	(revision 31697)
+++ src/wp-includes/class-wp-customize-manager.php	(working copy)
@@ -1139,6 +1139,7 @@
 
 		/* Control Types (custom control classes) */
 		$this->register_control_type( 'WP_Customize_Color_Control' );
+		$this->register_control_type( 'WP_Customize_Media_Control' );
 		$this->register_control_type( 'WP_Customize_Upload_Control' );
 		$this->register_control_type( 'WP_Customize_Image_Control' );
 		$this->register_control_type( 'WP_Customize_Background_Image_Control' );
