diff --git a/cms/djangoapps/contentstore/tests/test_contentstore.py b/cms/djangoapps/contentstore/tests/test_contentstore.py
index 09413be7b77fd7496a6805eb41907b0cdc02dc81..2ffd5a3684c1d69ad70b2cfc76884421276ade5a 100644
--- a/cms/djangoapps/contentstore/tests/test_contentstore.py
+++ b/cms/djangoapps/contentstore/tests/test_contentstore.py
@@ -107,8 +107,8 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
         expected_types is the list of elements that should appear on the page.
 
         expected_types and component_types should be similar, but not
-        exactly the same -- for example, 'videoalpha' in
-        component_types should cause 'Video Alpha' to be present.
+        exactly the same -- for example, 'video' in
+        component_types should cause 'Video' to be present.
         """
         store = modulestore('direct')
         import_from_xml(store, 'common/test/data/', ['simple'])
@@ -143,7 +143,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
                                                                  'Peer Grading Interface'])
 
     def test_advanced_components_require_two_clicks(self):
-        self.check_components_on_page(['videoalpha'], ['Video Alpha'])
+        self.check_components_on_page(['video'], ['Video'])
 
     def test_malformed_edit_unit_request(self):
         store = modulestore('direct')
@@ -1624,7 +1624,7 @@ class MetadataSaveTestCase(ModuleStoreTestCase):
         constructor are correctly persisted.
         """
         # We should start with a source field, from the XML's <source/> tag
-        self.assertIn('source', own_metadata(self.descriptor))
+        self.assertIn('html5_sources', own_metadata(self.descriptor))
         attrs_to_strip = {
             'show_captions',
             'youtube_id_1_0',
@@ -1634,6 +1634,7 @@ class MetadataSaveTestCase(ModuleStoreTestCase):
             'start_time',
             'end_time',
             'source',
+            'html5_sources',
             'track'
         }
         # We strip out all metadata fields to reproduce a bug where
@@ -1646,11 +1647,11 @@ class MetadataSaveTestCase(ModuleStoreTestCase):
                 field.delete_from(self.descriptor)
 
         # Assert that we correctly stripped the field
-        self.assertNotIn('source', own_metadata(self.descriptor))
+        self.assertNotIn('html5_sources', own_metadata(self.descriptor))
         get_modulestore(self.descriptor.location).update_metadata(
             self.descriptor.location,
             own_metadata(self.descriptor)
         )
         module = get_modulestore(self.descriptor.location).get_item(self.descriptor.location)
         # Assert that get_item correctly sets the metadata
-        self.assertIn('source', own_metadata(module))
+        self.assertIn('html5_sources', own_metadata(module))
diff --git a/cms/djangoapps/contentstore/views/component.py b/cms/djangoapps/contentstore/views/component.py
index 7cb503db1ebcd735f44825a2f9f8dba9c27fa83f..d7b41acb24fddd7112b1cd2a1035f737d904935a 100644
--- a/cms/djangoapps/contentstore/views/component.py
+++ b/cms/djangoapps/contentstore/views/component.py
@@ -49,7 +49,6 @@ NOTE_COMPONENT_TYPES = ['notes']
 ADVANCED_COMPONENT_TYPES = [
     'annotatable',
     'word_cloud',
-    'videoalpha',
     'graphical_slider_tool'
 ] + OPEN_ENDED_COMPONENT_TYPES + NOTE_COMPONENT_TYPES
 ADVANCED_COMPONENT_CATEGORY = 'advanced'
diff --git a/common/lib/xmodule/setup.py b/common/lib/xmodule/setup.py
index 6b106dd94db8ed499966c93f83e7f1ebaee52159..704de15ea77760e1538f88f789f4b7db5514951d 100644
--- a/common/lib/xmodule/setup.py
+++ b/common/lib/xmodule/setup.py
@@ -40,7 +40,7 @@ setup(
             "timelimit = xmodule.timelimit_module:TimeLimitDescriptor",
             "vertical = xmodule.vertical_module:VerticalDescriptor",
             "video = xmodule.video_module:VideoDescriptor",
-            "videoalpha = xmodule.videoalpha_module:VideoAlphaDescriptor",
+            "videoalpha = xmodule.video_module:VideoDescriptor",
             "videodev = xmodule.backcompat_module:TranslateCustomTagDescriptor",
             "videosequence = xmodule.seq_module:SequenceDescriptor",
             "discussion = xmodule.discussion_module:DiscussionDescriptor",
diff --git a/common/lib/xmodule/xmodule/tests/test_editing_module.py b/common/lib/xmodule/xmodule/tests/test_editing_module.py
index 03e257940f9ba754056866fc767d69698aeb7e47..838a4f9adaaf006635a526cf0ca5987ebe0b9d4b 100644
--- a/common/lib/xmodule/xmodule/tests/test_editing_module.py
+++ b/common/lib/xmodule/xmodule/tests/test_editing_module.py
@@ -33,7 +33,7 @@ class TabsEditingDescriptorTestCase(unittest.TestCase):
             },
             {
                 'name': "Subtitles",
-                'template': "videoalpha/subtitles.html",
+                'template': "video/subtitles.html",
             },
             {
                 'name': "Settings",
diff --git a/common/lib/xmodule/xmodule/tests/test_videoalpha.py b/common/lib/xmodule/xmodule/tests/test_video.py
similarity index 78%
rename from common/lib/xmodule/xmodule/tests/test_videoalpha.py
rename to common/lib/xmodule/xmodule/tests/test_video.py
index 76f86d6d4aa4571195af2f2b0504a924b58d8806..baafc05d450169cfd3f67d46498699420ac48bee 100644
--- a/common/lib/xmodule/xmodule/tests/test_videoalpha.py
+++ b/common/lib/xmodule/xmodule/tests/test_video.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #pylint: disable=W0212
-"""Test for Video Alpha Xmodule functional logic.
+"""Test for Video Xmodule functional logic.
 These test data read from xml, not from mongo.
 
 We have a ModuleStoreTestCase class defined in
@@ -17,37 +17,36 @@ import unittest
 from . import LogicTest
 from .import get_test_system
 from xmodule.modulestore import Location
-from xmodule.videoalpha_module import VideoAlphaDescriptor, _create_youtube_string
-from xmodule.video_module import VideoDescriptor
+from xmodule.video_module import VideoDescriptor, _create_youtube_string
 from .test_import import DummySystem
 
 from textwrap import dedent
 
 
-class VideoAlphaModuleTest(LogicTest):
-    """Logic tests for VideoAlpha Xmodule."""
-    descriptor_class = VideoAlphaDescriptor
+class VideoModuleTest(LogicTest):
+    """Logic tests for Video Xmodule."""
+    descriptor_class = VideoDescriptor
 
     raw_model_data = {
-        'data': '<videoalpha />'
+        'data': '<video />'
     }
 
     def test_parse_time_empty(self):
         """Ensure parse_time returns correctly with None or empty string."""
         expected = ''
-        self.assertEqual(VideoAlphaDescriptor._parse_time(None), expected)
-        self.assertEqual(VideoAlphaDescriptor._parse_time(''), expected)
+        self.assertEqual(VideoDescriptor._parse_time(None), expected)
+        self.assertEqual(VideoDescriptor._parse_time(''), expected)
 
     def test_parse_time(self):
         """Ensure that times are parsed correctly into seconds."""
         expected = 247
-        output = VideoAlphaDescriptor._parse_time('00:04:07')
+        output = VideoDescriptor._parse_time('00:04:07')
         self.assertEqual(output, expected)
 
     def test_parse_youtube(self):
         """Test parsing old-style Youtube ID strings into a dict."""
         youtube_str = '0.75:jNCf2gIqpeE,1.00:ZwkTiUPN0mg,1.25:rsq9auxASqI,1.50:kMyNdzVHHgg'
-        output = VideoAlphaDescriptor._parse_youtube(youtube_str)
+        output = VideoDescriptor._parse_youtube(youtube_str)
         self.assertEqual(output, {'0.75': 'jNCf2gIqpeE',
                                   '1.00': 'ZwkTiUPN0mg',
                                   '1.25': 'rsq9auxASqI',
@@ -59,7 +58,7 @@ class VideoAlphaModuleTest(LogicTest):
         empty string.
         """
         youtube_str = '0.75:jNCf2gIqpeE'
-        output = VideoAlphaDescriptor._parse_youtube(youtube_str)
+        output = VideoDescriptor._parse_youtube(youtube_str)
         self.assertEqual(output, {'0.75': 'jNCf2gIqpeE',
                                   '1.00': '',
                                   '1.25': '',
@@ -72,8 +71,8 @@ class VideoAlphaModuleTest(LogicTest):
         youtube_str = '1.00:p2Q6BrNhdh8'
         youtube_str_hack = '1.0:p2Q6BrNhdh8'
         self.assertEqual(
-            VideoAlphaDescriptor._parse_youtube(youtube_str),
-            VideoAlphaDescriptor._parse_youtube(youtube_str_hack)
+            VideoDescriptor._parse_youtube(youtube_str),
+            VideoDescriptor._parse_youtube(youtube_str_hack)
         )
 
     def test_parse_youtube_empty(self):
@@ -82,7 +81,7 @@ class VideoAlphaModuleTest(LogicTest):
         that well.
         """
         self.assertEqual(
-            VideoAlphaDescriptor._parse_youtube(''),
+            VideoDescriptor._parse_youtube(''),
             {'0.75': '',
              '1.00': '',
              '1.25': '',
@@ -90,12 +89,12 @@ class VideoAlphaModuleTest(LogicTest):
         )
 
 
-class VideoAlphaDescriptorTest(unittest.TestCase):
-    """Test for VideoAlphaDescriptor"""
+class VideoDescriptorTest(unittest.TestCase):
+    """Test for VideoDescriptor"""
 
     def setUp(self):
         system = get_test_system()
-        self.descriptor = VideoAlphaDescriptor(
+        self.descriptor = VideoDescriptor(
             runtime=system,
             model_data={})
 
@@ -117,9 +116,9 @@ class VideoAlphaDescriptorTest(unittest.TestCase):
         back out to XML.
         """
         system = DummySystem(load_error_modules=True)
-        location = Location(["i4x", "edX", "videoalpha", "default", "SampleProblem1"])
+        location = Location(["i4x", "edX", "video", "default", "SampleProblem1"])
         model_data = {'location': location}
-        descriptor = VideoAlphaDescriptor(system, model_data)
+        descriptor = VideoDescriptor(system, model_data)
         descriptor.youtube_id_0_75 = 'izygArpw-Qo'
         descriptor.youtube_id_1_0 = 'p2Q6BrNhdh8'
         descriptor.youtube_id_1_25 = '1EeWXzPdhSA'
@@ -133,9 +132,9 @@ class VideoAlphaDescriptorTest(unittest.TestCase):
         in the output string.
         """
         system = DummySystem(load_error_modules=True)
-        location = Location(["i4x", "edX", "videoalpha", "default", "SampleProblem1"])
+        location = Location(["i4x", "edX", "video", "default", "SampleProblem1"])
         model_data = {'location': location}
-        descriptor = VideoAlphaDescriptor(system, model_data)
+        descriptor = VideoDescriptor(system, model_data)
         descriptor.youtube_id_0_75 = 'izygArpw-Qo'
         descriptor.youtube_id_1_0 = 'p2Q6BrNhdh8'
         descriptor.youtube_id_1_25 = '1EeWXzPdhSA'
@@ -143,9 +142,9 @@ class VideoAlphaDescriptorTest(unittest.TestCase):
         self.assertEqual(_create_youtube_string(descriptor), expected)
 
 
-class VideoAlphaDescriptorImportTestCase(unittest.TestCase):
+class VideoDescriptorImportTestCase(unittest.TestCase):
     """
-    Make sure that VideoAlphaDescriptor can import an old XML-based video correctly.
+    Make sure that VideoDescriptor can import an old XML-based video correctly.
     """
 
     def assert_attributes_equal(self, video, attrs):
@@ -158,7 +157,7 @@ class VideoAlphaDescriptorImportTestCase(unittest.TestCase):
 
     def test_constructor(self):
         sample_xml = '''
-            <videoalpha display_name="Test Video"
+            <video display_name="Test Video"
                    youtube="1.0:p2Q6BrNhdh8,0.75:izygArpw-Qo,1.25:1EeWXzPdhSA,1.5:rABDYkeK0x8"
                    show_captions="false"
                    start_time="00:00:01"
@@ -166,14 +165,14 @@ class VideoAlphaDescriptorImportTestCase(unittest.TestCase):
               <source src="http://www.example.com/source.mp4"/>
               <source src="http://www.example.com/source.ogg"/>
               <track src="http://www.example.com/track"/>
-            </videoalpha>
+            </video>
         '''
-        location = Location(["i4x", "edX", "videoalpha", "default",
+        location = Location(["i4x", "edX", "video", "default",
                              "SampleProblem1"])
         model_data = {'data': sample_xml,
                       'location': location}
         system = DummySystem(load_error_modules=True)
-        descriptor = VideoAlphaDescriptor(system, model_data)
+        descriptor = VideoDescriptor(system, model_data)
         self.assert_attributes_equal(descriptor, {
             'youtube_id_0_75': 'izygArpw-Qo',
             'youtube_id_1_0': 'p2Q6BrNhdh8',
@@ -190,16 +189,16 @@ class VideoAlphaDescriptorImportTestCase(unittest.TestCase):
     def test_from_xml(self):
         module_system = DummySystem(load_error_modules=True)
         xml_data = '''
-            <videoalpha display_name="Test Video"
+            <video display_name="Test Video"
                    youtube="1.0:p2Q6BrNhdh8,0.75:izygArpw-Qo,1.25:1EeWXzPdhSA,1.5:rABDYkeK0x8"
                    show_captions="false"
                    start_time="00:00:01"
                    end_time="00:01:00">
               <source src="http://www.example.com/source.mp4"/>
               <track src="http://www.example.com/track"/>
-            </videoalpha>
+            </video>
         '''
-        output = VideoAlphaDescriptor.from_xml(xml_data, module_system)
+        output = VideoDescriptor.from_xml(xml_data, module_system)
         self.assert_attributes_equal(output, {
             'youtube_id_0_75': 'izygArpw-Qo',
             'youtube_id_1_0': 'p2Q6BrNhdh8',
@@ -221,14 +220,14 @@ class VideoAlphaDescriptorImportTestCase(unittest.TestCase):
         """
         module_system = DummySystem(load_error_modules=True)
         xml_data = '''
-            <videoalpha display_name="Test Video"
+            <video display_name="Test Video"
                    youtube="1.0:p2Q6BrNhdh8,1.25:1EeWXzPdhSA"
                    show_captions="true">
               <source src="http://www.example.com/source.mp4"/>
               <track src="http://www.example.com/track"/>
-            </videoalpha>
+            </video>
         '''
-        output = VideoAlphaDescriptor.from_xml(xml_data, module_system)
+        output = VideoDescriptor.from_xml(xml_data, module_system)
         self.assert_attributes_equal(output, {
             'youtube_id_0_75': '',
             'youtube_id_1_0': 'p2Q6BrNhdh8',
@@ -248,8 +247,8 @@ class VideoAlphaDescriptorImportTestCase(unittest.TestCase):
         Make sure settings are correct if none are explicitly set in XML.
         """
         module_system = DummySystem(load_error_modules=True)
-        xml_data = '<videoalpha></videoalpha>'
-        output = VideoAlphaDescriptor.from_xml(xml_data, module_system)
+        xml_data = '<video></video>'
+        output = VideoDescriptor.from_xml(xml_data, module_system)
         self.assert_attributes_equal(output, {
             'youtube_id_0_75': '',
             'youtube_id_1_0': 'OEoXaMPEzfM',
@@ -270,16 +269,16 @@ class VideoAlphaDescriptorImportTestCase(unittest.TestCase):
         """
         module_system = DummySystem(load_error_modules=True)
         xml_data = """
-            <videoalpha display_name="Test Video"
+            <video display_name="Test Video"
                    youtube="1.0:p2Q6BrNhdh8,0.75:izygArpw-Qo,1.25:1EeWXzPdhSA,1.5:rABDYkeK0x8"
                    show_captions="false"
                    from="00:00:01"
                    to="00:01:00">
               <source src="http://www.example.com/source.mp4"/>
               <track src="http://www.example.com/track"/>
-            </videoalpha>
+            </video>
         """
-        output = VideoAlphaDescriptor.from_xml(xml_data, module_system)
+        output = VideoDescriptor.from_xml(xml_data, module_system)
         self.assert_attributes_equal(output, {
             'youtube_id_0_75': 'izygArpw-Qo',
             'youtube_id_1_0': 'p2Q6BrNhdh8',
@@ -295,7 +294,7 @@ class VideoAlphaDescriptorImportTestCase(unittest.TestCase):
 
     def test_old_video_data(self):
         """
-        Ensure that Video Alpha is able to read VideoModule's model data.
+        Ensure that Video is able to read VideoModule's model data.
         """
         module_system = DummySystem(load_error_modules=True)
         xml_data = """
@@ -309,8 +308,7 @@ class VideoAlphaDescriptorImportTestCase(unittest.TestCase):
             </video>
         """
         video = VideoDescriptor.from_xml(xml_data, module_system)
-        video_alpha = VideoAlphaDescriptor(module_system, video._model_data)
-        self.assert_attributes_equal(video_alpha, {
+        self.assert_attributes_equal(video, {
             'youtube_id_0_75': 'izygArpw-Qo',
             'youtube_id_1_0': 'p2Q6BrNhdh8',
             'youtube_id_1_25': '1EeWXzPdhSA',
@@ -324,17 +322,17 @@ class VideoAlphaDescriptorImportTestCase(unittest.TestCase):
         })
 
 
-class VideoAlphaExportTestCase(unittest.TestCase):
+class VideoExportTestCase(unittest.TestCase):
     """
-    Make sure that VideoAlphaDescriptor can export itself to XML
+    Make sure that VideoDescriptor can export itself to XML
     correctly.
     """
 
     def test_export_to_xml(self):
         """Test that we write the correct XML on export."""
         module_system = DummySystem(load_error_modules=True)
-        location = Location(["i4x", "edX", "videoalpha", "default", "SampleProblem1"])
-        desc = VideoAlphaDescriptor(module_system, {'location': location})
+        location = Location(["i4x", "edX", "video", "default", "SampleProblem1"])
+        desc = VideoDescriptor(module_system, {'location': location})
 
         desc.youtube_id_0_75 = 'izygArpw-Qo'
         desc.youtube_id_1_0 = 'p2Q6BrNhdh8'
@@ -348,11 +346,11 @@ class VideoAlphaExportTestCase(unittest.TestCase):
 
         xml = desc.export_to_xml(None)  # We don't use the `resource_fs` parameter
         expected = dedent('''\
-         <videoalpha display_name="Video Alpha" start_time="0:00:01" youtube="0.75:izygArpw-Qo,1.00:p2Q6BrNhdh8,1.25:1EeWXzPdhSA,1.50:rABDYkeK0x8" show_captions="false" end_time="0:01:00">
+         <video display_name="Video" start_time="0:00:01" youtube="0.75:izygArpw-Qo,1.00:p2Q6BrNhdh8,1.25:1EeWXzPdhSA,1.50:rABDYkeK0x8" show_captions="false" end_time="0:01:00">
            <source src="http://www.example.com/source.mp4"/>
            <source src="http://www.example.com/source.ogg"/>
            <track src="http://www.example.com/track"/>
-         </videoalpha>
+         </video>
         ''')
 
         self.assertEquals(expected, xml)
@@ -360,10 +358,10 @@ class VideoAlphaExportTestCase(unittest.TestCase):
     def test_export_to_xml_empty_parameters(self):
         """Test XML export with defaults."""
         module_system = DummySystem(load_error_modules=True)
-        location = Location(["i4x", "edX", "videoalpha", "default", "SampleProblem1"])
-        desc = VideoAlphaDescriptor(module_system, {'location': location})
+        location = Location(["i4x", "edX", "video", "default", "SampleProblem1"])
+        desc = VideoDescriptor(module_system, {'location': location})
 
         xml = desc.export_to_xml(None)
-        expected = '<videoalpha display_name="Video Alpha" youtube="1.00:OEoXaMPEzfM" show_captions="true"/>\n'
+        expected = '<video display_name="Video" youtube="1.00:OEoXaMPEzfM" show_captions="true"/>\n'
 
         self.assertEquals(expected, xml)
diff --git a/common/lib/xmodule/xmodule/tests/test_xblock_wrappers.py b/common/lib/xmodule/xmodule/tests/test_xblock_wrappers.py
index 90ff209c7d3ded1cc0566cee852b895cee5ceee6..c98f980c6220b7d81c8447af87073a050dac7586 100644
--- a/common/lib/xmodule/xmodule/tests/test_xblock_wrappers.py
+++ b/common/lib/xmodule/xmodule/tests/test_xblock_wrappers.py
@@ -16,10 +16,9 @@ from xmodule.gst_module import GraphicalSliderToolDescriptor
 from xmodule.html_module import HtmlDescriptor
 from xmodule.peer_grading_module import PeerGradingDescriptor
 from xmodule.poll_module import PollDescriptor
-from xmodule.video_module import VideoDescriptor
 from xmodule.word_cloud_module import WordCloudDescriptor
 from xmodule.crowdsource_hinter import CrowdsourceHinterDescriptor
-from xmodule.videoalpha_module import VideoAlphaDescriptor
+from xmodule.video_module import VideoDescriptor
 from xmodule.seq_module import SequenceDescriptor
 from xmodule.conditional_module import ConditionalDescriptor
 from xmodule.randomize_module import RandomizeDescriptor
@@ -35,9 +34,8 @@ LEAF_XMODULES = (
     HtmlDescriptor,
     PeerGradingDescriptor,
     PollDescriptor,
-    VideoDescriptor,
     # This is being excluded because it has dependencies on django
-    #VideoAlphaDescriptor,
+    #VideoDescriptor,
     WordCloudDescriptor,
 )
 
diff --git a/common/lib/xmodule/xmodule/video_module.py b/common/lib/xmodule/xmodule/video_module.py
index 763975fc3bc95e315394b73933c416bbd1b923c2..c18d6d066b1cea476aa09e49619fa4798c422452 100644
--- a/common/lib/xmodule/xmodule/video_module.py
+++ b/common/lib/xmodule/xmodule/video_module.py
@@ -1,20 +1,34 @@
 # pylint: disable=W0223
-"""Video is ungraded Xmodule for support video content."""
+"""Video is ungraded Xmodule for support video content.
+It's new improved video module, which support additional feature:
+
+- Can play non-YouTube video sources via in-browser HTML5 video player.
+- YouTube defaults to HTML5 mode from the start.
+- Speed changes in both YouTube and non-YouTube videos happen via
+in-browser HTML5 video method (when in HTML5 mode).
+- Navigational subtitles can be disabled altogether via an attribute
+in XML.
+"""
 
 import json
 import logging
 
 from lxml import etree
-from pkg_resources import resource_string, resource_listdir
-import datetime
-import time
+from pkg_resources import resource_string
 
 from django.http import Http404
+from django.conf import settings
 
 from xmodule.x_module import XModule
+from xmodule.editing_module import TabsEditingDescriptor
 from xmodule.raw_module import EmptyDataRawDescriptor
-from xmodule.editing_module import MetadataOnlyEditingDescriptor
-from xblock.core import Integer, Scope, String, Float, Boolean
+from xmodule.modulestore.mongo import MongoModuleStore
+from xmodule.modulestore.django import modulestore
+from xmodule.contentstore.content import StaticContent
+from xblock.core import Scope, String, Boolean, Float, List, Integer
+
+import datetime
+import time
 
 log = logging.getLogger(__name__)
 
@@ -22,51 +36,118 @@ log = logging.getLogger(__name__)
 class VideoFields(object):
     """Fields for `VideoModule` and `VideoDescriptor`."""
     display_name = String(
-        display_name="Display Name",
-        help="This name appears in the horizontal navigation at the top of the page.",
+        display_name="Display Name", help="Display name for this module.",
+        default="Video",
+        scope=Scope.settings
+    )
+    position = Integer(
+        help="Current position in the video",
+        scope=Scope.user_state,
+        default=0
+    )
+    show_captions = Boolean(
+        help="This controls whether or not captions are shown by default.",
+        display_name="Show Captions",
         scope=Scope.settings,
-        # it'd be nice to have a useful default but it screws up other things; so,
-        # use display_name_with_default for those
-        default="Video"
+        default=True
     )
-    data = String(
-        help="XML data for the problem",
-        default='',
-        scope=Scope.content
+    # TODO: This should be moved to Scope.content, but this will
+    # require data migration to support the old video module.
+    youtube_id_1_0 = String(
+        help="This is the Youtube ID reference for the normal speed video.",
+        display_name="Youtube ID",
+        scope=Scope.settings,
+        default="OEoXaMPEzfM"
+    )
+    youtube_id_0_75 = String(
+        help="The Youtube ID for the .75x speed video.",
+        display_name="Youtube ID for .75x speed",
+        scope=Scope.settings,
+        default=""
+    )
+    youtube_id_1_25 = String(
+        help="The Youtube ID for the 1.25x speed video.",
+        display_name="Youtube ID for 1.25x speed",
+        scope=Scope.settings,
+        default=""
+    )
+    youtube_id_1_5 = String(
+        help="The Youtube ID for the 1.5x speed video.",
+        display_name="Youtube ID for 1.5x speed",
+        scope=Scope.settings,
+        default=""
+    )
+    start_time = Float(
+        help="Start time for the video.",
+        display_name="Start Time",
+        scope=Scope.settings,
+        default=0.0
+    )
+    end_time = Float(
+        help="End time for the video.",
+        display_name="End Time",
+        scope=Scope.settings,
+        default=0.0
+    )
+    source = String(
+        help="The external URL to download the video. This appears as a link beneath the video.",
+        display_name="Download Video",
+        scope=Scope.settings,
+        default=""
+    )
+    html5_sources = List(
+        help="A list of filenames to be used with HTML5 video. The first supported filetype will be displayed.",
+        display_name="Video Sources",
+        scope=Scope.settings,
+        default=[]
+    )
+    track = String(
+        help="The external URL to download the subtitle track. This appears as a link beneath the video.",
+        display_name="Download Track",
+        scope=Scope.settings,
+        default=""
+    )
+    sub = String(
+        help="The name of the subtitle track (for non-Youtube videos).",
+        display_name="HTML5 Subtitles",
+        scope=Scope.settings,
+        default=""
     )
-    position = Integer(help="Current position in the video", scope=Scope.user_state, default=0)
-    show_captions = Boolean(help="This controls whether or not captions are shown by default.", display_name="Show Captions", scope=Scope.settings, default=True)
-    youtube_id_1_0 = String(help="This is the Youtube ID reference for the normal speed video.", display_name="Default Speed", scope=Scope.settings, default="OEoXaMPEzfM")
-    youtube_id_0_75 = String(help="The Youtube ID for the .75x speed video.", display_name="Speed: .75x", scope=Scope.settings, default="")
-    youtube_id_1_25 = String(help="The Youtube ID for the 1.25x speed video.", display_name="Speed: 1.25x", scope=Scope.settings, default="")
-    youtube_id_1_5 = String(help="The Youtube ID for the 1.5x speed video.", display_name="Speed: 1.5x", scope=Scope.settings, default="")
-    start_time = Float(help="Time the video starts", display_name="Start Time", scope=Scope.settings, default=0.0)
-    end_time = Float(help="Time the video ends", display_name="End Time", scope=Scope.settings, default=0.0)
-    source = String(help="The external URL to download the video. This appears as a link beneath the video.", display_name="Download Video", scope=Scope.settings, default="")
-    track = String(help="The external URL to download the subtitle track. This appears as a link beneath the video.", display_name="Download Track", scope=Scope.settings, default="")
 
 
 class VideoModule(VideoFields, XModule):
-    """Video Xmodule."""
+    """
+    XML source example:
+
+        <video show_captions="true"
+            youtube="0.75:jNCf2gIqpeE,1.0:ZwkTiUPN0mg,1.25:rsq9auxASqI,1.50:kMyNdzVHHgg"
+            url_name="lecture_21_3" display_name="S19V3: Vacancies"
+        >
+            <source src=".../mit-3091x/M-3091X-FA12-L21-3_100.mp4"/>
+            <source src=".../mit-3091x/M-3091X-FA12-L21-3_100.webm"/>
+            <source src=".../mit-3091x/M-3091X-FA12-L21-3_100.ogv"/>
+        </video>
+    """
     video_time = 0
     icon_class = 'video'
 
     js = {
-        'coffee': [
-            resource_string(__name__, 'js/src/time.coffee'),
-            resource_string(__name__, 'js/src/video/display.coffee')
-        ] +
-        [resource_string(__name__, 'js/src/video/display/' + filename)
-         for filename
-         in sorted(resource_listdir(__name__, 'js/src/video/display'))
-         if filename.endswith('.coffee')]
+        'js': [
+            resource_string(__name__, 'js/src/video/01_initialize.js'),
+            resource_string(__name__, 'js/src/video/02_html5_video.js'),
+            resource_string(__name__, 'js/src/video/03_video_player.js'),
+            resource_string(__name__, 'js/src/video/04_video_control.js'),
+            resource_string(__name__, 'js/src/video/05_video_quality_control.js'),
+            resource_string(__name__, 'js/src/video/06_video_progress_slider.js'),
+            resource_string(__name__, 'js/src/video/07_video_volume_control.js'),
+            resource_string(__name__, 'js/src/video/08_video_speed_control.js'),
+            resource_string(__name__, 'js/src/video/09_video_caption.js'),
+            resource_string(__name__, 'js/src/video/10_main.js')
+        ]
     }
     css = {'scss': [resource_string(__name__, 'css/video/display.scss')]}
     js_module_name = "Video"
 
-    def __init__(self, *args, **kwargs):
-        XModule.__init__(self, *args, **kwargs)
-
     def handle_ajax(self, dispatch, data):
         """This is not being called right now and we raise 404 error."""
         log.debug(u"GET {0}".format(data))
@@ -78,41 +159,59 @@ class VideoModule(VideoFields, XModule):
         return json.dumps({'position': self.position})
 
     def get_html(self):
+        if isinstance(modulestore(), MongoModuleStore):
+            caption_asset_path = StaticContent.get_base_url_path_for_course_assets(self.location) + '/subs_'
+        else:
+            # VS[compat]
+            # cdodge: filesystem static content support.
+            caption_asset_path = "/static/subs/"
+
+        get_ext = lambda filename: filename.rpartition('.')[-1]
+        sources = {get_ext(src): src for src in self.html5_sources}
+        sources['main'] = self.source
+
         return self.system.render_template('video.html', {
-            'youtube_id_0_75': self.youtube_id_0_75,
-            'youtube_id_1_0': self.youtube_id_1_0,
-            'youtube_id_1_25': self.youtube_id_1_25,
-            'youtube_id_1_5': self.youtube_id_1_5,
+            'youtube_streams': _create_youtube_string(self),
             'id': self.location.html_id(),
-            'position': self.position,
-            'source': self.source,
+            'sub': self.sub,
+            'sources': sources,
             'track': self.track,
             'display_name': self.display_name_with_default,
-            'caption_asset_path': "/static/subs/",
-            'show_captions': 'true' if self.show_captions else 'false',
+            # This won't work when we move to data that
+            # isn't on the filesystem
+            'data_dir': getattr(self, 'data_dir', None),
+            'caption_asset_path': caption_asset_path,
+            'show_captions': json.dumps(self.show_captions),
             'start': self.start_time,
-            'end': self.end_time
+            'end': self.end_time,
+            'autoplay': settings.MITX_FEATURES.get('AUTOPLAY_VIDEOS', True)
         })
 
 
-class VideoDescriptor(VideoFields,
-                      MetadataOnlyEditingDescriptor,
-                      EmptyDataRawDescriptor):
+class VideoDescriptor(VideoFields, TabsEditingDescriptor, EmptyDataRawDescriptor):
+    """Descriptor for `VideoModule`."""
     module_class = VideoModule
 
+    tabs = [
+        # {
+        #     'name': "Subtitles",
+        #     'template': "video/subtitles.html",
+        # },
+        {
+            'name': "Settings",
+            'template': "tabs/metadata-edit-tab.html",
+            'current': True
+        }
+    ]
+
     def __init__(self, *args, **kwargs):
         super(VideoDescriptor, self).__init__(*args, **kwargs)
-        # If we don't have a `youtube_id_1_0`, this is an XML course
-        # and we parse out the fields.
-        if self.data and 'youtube_id_1_0' not in self._model_data:
-            _parse_video_xml(self, self.data)
-
-    @property
-    def non_editable_metadata_fields(self):
-        non_editable_fields = super(MetadataOnlyEditingDescriptor, self).non_editable_metadata_fields
-        non_editable_fields.extend([VideoModule.start_time,
-                                    VideoModule.end_time])
-        return non_editable_fields
+        # For backwards compatibility -- if we've got XML data, parse
+        # it out and set the metadata fields
+        if self.data:
+            model_data = VideoDescriptor._parse_video_xml(self.data)
+            self._model_data.update(model_data)
+            del self.data
 
     @classmethod
     def from_xml(cls, xml_data, system, org=None, course=None):
@@ -126,102 +225,143 @@ class VideoDescriptor(VideoFields,
         org and course are optional strings that will be used in the generated modules
             url identifiers
         """
+        # Calling from_xml of XmlDescritor, to get right Location, when importing from XML
         video = super(VideoDescriptor, cls).from_xml(xml_data, system, org, course)
-        _parse_video_xml(video, video.data)
         return video
 
+    def export_to_xml(self, resource_fs):
+        """
+        Returns an xml string representing this module.
+        """
+        xml = etree.Element('video')
+        attrs = {
+            'display_name': self.display_name,
+            'show_captions': json.dumps(self.show_captions),
+            'youtube': _create_youtube_string(self),
+            'start_time': datetime.timedelta(seconds=self.start_time),
+            'end_time': datetime.timedelta(seconds=self.end_time),
+            'sub': self.sub
+        }
+        for key, value in attrs.items():
+            if value:
+                xml.set(key, str(value))
+
+        for source in self.html5_sources:
+            ele = etree.Element('source')
+            ele.set('src', source)
+            xml.append(ele)
+
+        if self.track:
+            ele = etree.Element('track')
+            ele.set('src', self.track)
+            xml.append(ele)
+
+        return etree.tostring(xml, pretty_print=True)
+
+    @staticmethod
+    def _parse_youtube(data):
+        """
+        Parses a string of Youtube IDs such as "1.0:AXdE34_U,1.5:VO3SxfeD"
+        into a dictionary. Necessary for backwards compatibility with
+        XML-based courses.
+        """
+        ret = {'0.75': '', '1.00': '', '1.25': '', '1.50': ''}
+        if data == '':
+            return ret
+        videos = data.split(',')
+        for video in videos:
+            pieces = video.split(':')
+            # HACK
+            # To elaborate somewhat: in many LMS tests, the keys for
+            # Youtube IDs are inconsistent. Sometimes a particular
+            # speed isn't present, and formatting is also inconsistent
+            # ('1.0' versus '1.00'). So it's necessary to either do
+            # something like this or update all the tests to work
+            # properly.
+            ret['%.2f' % float(pieces[0])] = pieces[1]
+        return ret
 
-def _parse_video_xml(video, xml_data):
-    """
-    Parse video fields out of xml_data. The fields are set if they are
-    present in the XML.
-    """
-    if not xml_data:
-        return
-
-    xml = etree.fromstring(xml_data)
-
-    display_name = xml.get('display_name')
-    if display_name:
-        video.display_name = display_name
-
-    youtube = xml.get('youtube')
-    if youtube:
-        speeds = _parse_youtube(youtube)
-        if speeds['0.75']:
-            video.youtube_id_0_75 = speeds['0.75']
-        if speeds['1.00']:
-            video.youtube_id_1_0 = speeds['1.00']
-        if speeds['1.25']:
-            video.youtube_id_1_25 = speeds['1.25']
-        if speeds['1.50']:
-            video.youtube_id_1_5 = speeds['1.50']
-
-    show_captions = xml.get('show_captions')
-    if show_captions:
-        video.show_captions = json.loads(show_captions)
-
-    source = _get_first_external(xml, 'source')
-    if source:
-        video.source = source
-
-    track = _get_first_external(xml, 'track')
-    if track:
-        video.track = track
-
-    start_time = _parse_time(xml.get('from'))
-    if start_time:
-        video.start_time = start_time
-
-    end_time = _parse_time(xml.get('to'))
-    if end_time:
-        video.end_time = end_time
-
-
-def _get_first_external(xmltree, tag):
-    """
-    Returns the src attribute of the nested `tag` in `xmltree`, if it
-    exists.
-    """
-    for element in xmltree.findall(tag):
-        src = element.get('src')
-        if src:
-            return src
-    return None
-
-
-def _parse_youtube(data):
+    @staticmethod
+    def _parse_video_xml(xml_data):
+        """
+        Parse video fields out of xml_data. The fields are set if they are
+        present in the XML.
+        """
+        xml = etree.fromstring(xml_data)
+        model_data = {}
+
+        conversions = {
+            'show_captions': json.loads,
+            'start_time': VideoDescriptor._parse_time,
+            'end_time': VideoDescriptor._parse_time
+        }
+
+        # VideoModule and VideoModule use different names for
+        # these attributes -- need to convert between them
+        video_compat = {
+            'from': 'start_time',
+            'to': 'end_time'
+        }
+
+        sources = xml.findall('source')
+        if sources:
+            model_data['html5_sources'] = [ele.get('src') for ele in sources]
+            model_data['source'] = model_data['html5_sources'][0]
+
+        track = xml.find('track')
+        if track is not None:
+            model_data['track'] = track.get('src')
+
+        for attr, value in xml.items():
+            if attr in video_compat:
+                attr = video_compat[attr]
+            if attr == 'youtube':
+                speeds = VideoDescriptor._parse_youtube(value)
+                for speed, youtube_id in speeds.items():
+                    # should have made these youtube_id_1_00 for
+                    # cleanliness, but hindsight doesn't need glasses
+                    normalized_speed = speed[:-1] if speed.endswith('0') else speed
+                    # If the user has specified html5 sources, make sure we don't use the default video
+                    if youtube_id != '' or 'html5_sources' in model_data:
+                        model_data['youtube_id_{0}'.format(normalized_speed.replace('.', '_'))] = youtube_id
+            else:
+                #  Convert XML attrs into Python values.
+                if attr in conversions:
+                    value = conversions[attr](value)
+                model_data[attr] = value
+
+        return model_data
+
+    @staticmethod
+    def _parse_time(str_time):
+        """Converts s in '12:34:45' format to seconds. If s is
+        None, returns empty string"""
+        if not str_time:
+            return ''
+        else:
+            obj_time = time.strptime(str_time, '%H:%M:%S')
+            return datetime.timedelta(
+                hours=obj_time.tm_hour,
+                minutes=obj_time.tm_min,
+                seconds=obj_time.tm_sec
+            ).total_seconds()
+
+
+def _create_youtube_string(module):
     """
-    Parses a string of Youtube IDs such as "1.0:AXdE34_U,1.5:VO3SxfeD"
-    into a dictionary. Necessary for backwards compatibility with
-    XML-based courses.
+    Create a string of Youtube IDs from `module`'s metadata
+    attributes. Only writes a speed if an ID is present in the
+    module.  Necessary for backwards compatibility with XML-based
+    courses.
     """
-    ret = {'0.75': '', '1.00': '', '1.25': '', '1.50': ''}
-    if data == '':
-        return ret
-    videos = data.split(',')
-    for video in videos:
-        pieces = video.split(':')
-        # HACK
-        # To elaborate somewhat: in many LMS tests, the keys for
-        # Youtube IDs are inconsistent. Sometimes a particular
-        # speed isn't present, and formatting is also inconsistent
-        # ('1.0' versus '1.00'). So it's necessary to either do
-        # something like this or update all the tests to work
-        # properly.
-        ret['%.2f' % float(pieces[0])] = pieces[1]
-    return ret
-
-
-def _parse_time(str_time):
-    """Converts s in '12:34:45' format to seconds. If s is
-    None, returns empty string"""
-    if str_time is None or str_time == '':
-        return ''
-    else:
-        obj_time = time.strptime(str_time, '%H:%M:%S')
-        return datetime.timedelta(
-            hours=obj_time.tm_hour,
-            minutes=obj_time.tm_min,
-            seconds=obj_time.tm_sec
-        ).total_seconds()
+    youtube_ids = [
+        module.youtube_id_0_75,
+        module.youtube_id_1_0,
+        module.youtube_id_1_25,
+        module.youtube_id_1_5
+    ]
+    youtube_speeds = ['0.75', '1.00', '1.25', '1.50']
+    return ','.join([':'.join(pair)
+                     for pair
+                     in zip(youtube_speeds, youtube_ids)
+                     if pair[1]])
diff --git a/common/lib/xmodule/xmodule/videoalpha_module.py b/common/lib/xmodule/xmodule/videoalpha_module.py
deleted file mode 100644
index 176b19237792e28c638a2d8501e56907ef5c3882..0000000000000000000000000000000000000000
--- a/common/lib/xmodule/xmodule/videoalpha_module.py
+++ /dev/null
@@ -1,367 +0,0 @@
-# pylint: disable=W0223
-"""VideoAlpha is ungraded Xmodule for support video content.
-It's new improved video module, which support additional feature:
-
-- Can play non-YouTube video sources via in-browser HTML5 video player.
-- YouTube defaults to HTML5 mode from the start.
-- Speed changes in both YouTube and non-YouTube videos happen via
-in-browser HTML5 video method (when in HTML5 mode).
-- Navigational subtitles can be disabled altogether via an attribute
-in XML.
-"""
-
-import json
-import logging
-
-from lxml import etree
-from pkg_resources import resource_string
-
-from django.http import Http404
-from django.conf import settings
-
-from xmodule.x_module import XModule
-from xmodule.editing_module import TabsEditingDescriptor
-from xmodule.raw_module import EmptyDataRawDescriptor
-from xmodule.modulestore.mongo import MongoModuleStore
-from xmodule.modulestore.django import modulestore
-from xmodule.contentstore.content import StaticContent
-from xblock.core import Scope, String, Boolean, Float, List, Integer
-
-import datetime
-import time
-
-log = logging.getLogger(__name__)
-
-
-class VideoAlphaFields(object):
-    """Fields for `VideoAlphaModule` and `VideoAlphaDescriptor`."""
-    display_name = String(
-        display_name="Display Name", help="Display name for this module.",
-        default="Video Alpha",
-        scope=Scope.settings
-    )
-    position = Integer(
-        help="Current position in the video",
-        scope=Scope.user_state,
-        default=0
-    )
-    show_captions = Boolean(
-        help="This controls whether or not captions are shown by default.",
-        display_name="Show Captions",
-        scope=Scope.settings,
-        default=True
-    )
-    # TODO: This should be moved to Scope.content, but this will
-    # require data migration to support the old video module.
-    youtube_id_1_0 = String(
-        help="This is the Youtube ID reference for the normal speed video.",
-        display_name="Youtube ID",
-        scope=Scope.settings,
-        default="OEoXaMPEzfM"
-    )
-    youtube_id_0_75 = String(
-        help="The Youtube ID for the .75x speed video.",
-        display_name="Youtube ID for .75x speed",
-        scope=Scope.settings,
-        default=""
-    )
-    youtube_id_1_25 = String(
-        help="The Youtube ID for the 1.25x speed video.",
-        display_name="Youtube ID for 1.25x speed",
-        scope=Scope.settings,
-        default=""
-    )
-    youtube_id_1_5 = String(
-        help="The Youtube ID for the 1.5x speed video.",
-        display_name="Youtube ID for 1.5x speed",
-        scope=Scope.settings,
-        default=""
-    )
-    start_time = Float(
-        help="Start time for the video.",
-        display_name="Start Time",
-        scope=Scope.settings,
-        default=0.0
-    )
-    end_time = Float(
-        help="End time for the video.",
-        display_name="End Time",
-        scope=Scope.settings,
-        default=0.0
-    )
-    source = String(
-        help="The external URL to download the video. This appears as a link beneath the video.",
-        display_name="Download Video",
-        scope=Scope.settings,
-        default=""
-    )
-    html5_sources = List(
-        help="A list of filenames to be used with HTML5 video. The first supported filetype will be displayed.",
-        display_name="Video Sources",
-        scope=Scope.settings,
-        default=[]
-    )
-    track = String(
-        help="The external URL to download the subtitle track. This appears as a link beneath the video.",
-        display_name="Download Track",
-        scope=Scope.settings,
-        default=""
-    )
-    sub = String(
-        help="The name of the subtitle track (for non-Youtube videos).",
-        display_name="HTML5 Subtitles",
-        scope=Scope.settings,
-        default=""
-    )
-
-
-class VideoAlphaModule(VideoAlphaFields, XModule):
-    """
-    XML source example:
-
-        <videoalpha show_captions="true"
-            youtube="0.75:jNCf2gIqpeE,1.0:ZwkTiUPN0mg,1.25:rsq9auxASqI,1.50:kMyNdzVHHgg"
-            url_name="lecture_21_3" display_name="S19V3: Vacancies"
-        >
-            <source src=".../mit-3091x/M-3091X-FA12-L21-3_100.mp4"/>
-            <source src=".../mit-3091x/M-3091X-FA12-L21-3_100.webm"/>
-            <source src=".../mit-3091x/M-3091X-FA12-L21-3_100.ogv"/>
-        </videoalpha>
-    """
-    video_time = 0
-    icon_class = 'video'
-
-    js = {
-        'js': [
-            resource_string(__name__, 'js/src/videoalpha/01_initialize.js'),
-            resource_string(__name__, 'js/src/videoalpha/02_html5_video.js'),
-            resource_string(__name__, 'js/src/videoalpha/03_video_player.js'),
-            resource_string(__name__, 'js/src/videoalpha/04_video_control.js'),
-            resource_string(__name__, 'js/src/videoalpha/05_video_quality_control.js'),
-            resource_string(__name__, 'js/src/videoalpha/06_video_progress_slider.js'),
-            resource_string(__name__, 'js/src/videoalpha/07_video_volume_control.js'),
-            resource_string(__name__, 'js/src/videoalpha/08_video_speed_control.js'),
-            resource_string(__name__, 'js/src/videoalpha/09_video_caption.js'),
-            resource_string(__name__, 'js/src/videoalpha/10_main.js')
-        ]
-    }
-    css = {'scss': [resource_string(__name__, 'css/videoalpha/display.scss')]}
-    js_module_name = "VideoAlpha"
-
-    def handle_ajax(self, dispatch, data):
-        """This is not being called right now and we raise 404 error."""
-        log.debug(u"GET {0}".format(data))
-        log.debug(u"DISPATCH {0}".format(dispatch))
-        raise Http404()
-
-    def get_instance_state(self):
-        """Return information about state (position)."""
-        return json.dumps({'position': self.position})
-
-    def get_html(self):
-        if isinstance(modulestore(), MongoModuleStore):
-            caption_asset_path = StaticContent.get_base_url_path_for_course_assets(self.location) + '/subs_'
-        else:
-            # VS[compat]
-            # cdodge: filesystem static content support.
-            caption_asset_path = "/static/subs/"
-
-        get_ext = lambda filename: filename.rpartition('.')[-1]
-        sources = {get_ext(src): src for src in self.html5_sources}
-        sources['main'] = self.source
-
-        return self.system.render_template('videoalpha.html', {
-            'youtube_streams': _create_youtube_string(self),
-            'id': self.location.html_id(),
-            'sub': self.sub,
-            'sources': sources,
-            'track': self.track,
-            'display_name': self.display_name_with_default,
-            # This won't work when we move to data that
-            # isn't on the filesystem
-            'data_dir': getattr(self, 'data_dir', None),
-            'caption_asset_path': caption_asset_path,
-            'show_captions': json.dumps(self.show_captions),
-            'start': self.start_time,
-            'end': self.end_time,
-            'autoplay': settings.MITX_FEATURES.get('AUTOPLAY_VIDEOS', True)
-        })
-
-
-class VideoAlphaDescriptor(VideoAlphaFields, TabsEditingDescriptor, EmptyDataRawDescriptor):
-    """Descriptor for `VideoAlphaModule`."""
-    module_class = VideoAlphaModule
-
-    tabs = [
-        # {
-        #     'name': "Subtitles",
-        #     'template': "videoalpha/subtitles.html",
-        # },
-        {
-            'name': "Settings",
-            'template': "tabs/metadata-edit-tab.html",
-            'current': True
-        }
-    ]
-
-    def __init__(self, *args, **kwargs):
-        super(VideoAlphaDescriptor, self).__init__(*args, **kwargs)
-        # For backwards compatibility -- if we've got XML data, parse
-        # it out and set the metadata fields
-        if self.data:
-            model_data = VideoAlphaDescriptor._parse_video_xml(self.data)
-            self._model_data.update(model_data)
-            del self.data
-
-    @classmethod
-    def from_xml(cls, xml_data, system, org=None, course=None):
-        """
-        Creates an instance of this descriptor from the supplied xml_data.
-        This may be overridden by subclasses
-
-        xml_data: A string of xml that will be translated into data and children for
-            this module
-        system: A DescriptorSystem for interacting with external resources
-        org and course are optional strings that will be used in the generated modules
-            url identifiers
-        """
-        # Calling from_xml of XmlDescritor, to get right Location, when importing from XML
-        video = super(VideoAlphaDescriptor, cls).from_xml(xml_data, system, org, course)
-        return video
-
-    def export_to_xml(self, resource_fs):
-        """
-        Returns an xml string representing this module.
-        """
-        xml = etree.Element('videoalpha')
-        attrs = {
-            'display_name': self.display_name,
-            'show_captions': json.dumps(self.show_captions),
-            'youtube': _create_youtube_string(self),
-            'start_time': datetime.timedelta(seconds=self.start_time),
-            'end_time': datetime.timedelta(seconds=self.end_time),
-            'sub': self.sub
-        }
-        for key, value in attrs.items():
-            if value:
-                xml.set(key, str(value))
-
-        for source in self.html5_sources:
-            ele = etree.Element('source')
-            ele.set('src', source)
-            xml.append(ele)
-
-        if self.track:
-            ele = etree.Element('track')
-            ele.set('src', self.track)
-            xml.append(ele)
-
-        return etree.tostring(xml, pretty_print=True)
-
-    @staticmethod
-    def _parse_youtube(data):
-        """
-        Parses a string of Youtube IDs such as "1.0:AXdE34_U,1.5:VO3SxfeD"
-        into a dictionary. Necessary for backwards compatibility with
-        XML-based courses.
-        """
-        ret = {'0.75': '', '1.00': '', '1.25': '', '1.50': ''}
-        if data == '':
-            return ret
-        videos = data.split(',')
-        for video in videos:
-            pieces = video.split(':')
-            # HACK
-            # To elaborate somewhat: in many LMS tests, the keys for
-            # Youtube IDs are inconsistent. Sometimes a particular
-            # speed isn't present, and formatting is also inconsistent
-            # ('1.0' versus '1.00'). So it's necessary to either do
-            # something like this or update all the tests to work
-            # properly.
-            ret['%.2f' % float(pieces[0])] = pieces[1]
-        return ret
-
-    @staticmethod
-    def _parse_video_xml(xml_data):
-        """
-        Parse video fields out of xml_data. The fields are set if they are
-        present in the XML.
-        """
-        xml = etree.fromstring(xml_data)
-        model_data = {}
-
-        conversions = {
-            'show_captions': json.loads,
-            'start_time': VideoAlphaDescriptor._parse_time,
-            'end_time': VideoAlphaDescriptor._parse_time
-        }
-
-        # VideoModule and VideoAlphaModule use different names for
-        # these attributes -- need to convert between them
-        video_compat = {
-            'from': 'start_time',
-            'to': 'end_time'
-        }
-
-        sources = xml.findall('source')
-        if sources:
-            model_data['html5_sources'] = [ele.get('src') for ele in sources]
-            model_data['source'] = model_data['html5_sources'][0]
-
-        track = xml.find('track')
-        if track is not None:
-            model_data['track'] = track.get('src')
-
-        for attr, value in xml.items():
-            if attr in video_compat:
-                attr = video_compat[attr]
-            if attr == 'youtube':
-                speeds = VideoAlphaDescriptor._parse_youtube(value)
-                for speed, youtube_id in speeds.items():
-                    # should have made these youtube_id_1_00 for
-                    # cleanliness, but hindsight doesn't need glasses
-                    normalized_speed = speed[:-1] if speed.endswith('0') else speed
-                    # If the user has specified html5 sources, make sure we don't use the default video
-                    if youtube_id != '' or 'html5_sources' in model_data:
-                        model_data['youtube_id_{0}'.format(normalized_speed.replace('.', '_'))] = youtube_id
-            else:
-                #  Convert XML attrs into Python values.
-                if attr in conversions:
-                    value = conversions[attr](value)
-                model_data[attr] = value
-
-        return model_data
-
-    @staticmethod
-    def _parse_time(str_time):
-        """Converts s in '12:34:45' format to seconds. If s is
-        None, returns empty string"""
-        if not str_time:
-            return ''
-        else:
-            obj_time = time.strptime(str_time, '%H:%M:%S')
-            return datetime.timedelta(
-                hours=obj_time.tm_hour,
-                minutes=obj_time.tm_min,
-                seconds=obj_time.tm_sec
-            ).total_seconds()
-
-
-def _create_youtube_string(module):
-    """
-    Create a string of Youtube IDs from `module`'s metadata
-    attributes. Only writes a speed if an ID is present in the
-    module.  Necessary for backwards compatibility with XML-based
-    courses.
-    """
-    youtube_ids = [
-        module.youtube_id_0_75,
-        module.youtube_id_1_0,
-        module.youtube_id_1_25,
-        module.youtube_id_1_5
-    ]
-    youtube_speeds = ['0.75', '1.00', '1.25', '1.50']
-    return ','.join([':'.join(pair)
-                     for pair
-                     in zip(youtube_speeds, youtube_ids)
-                     if pair[1]])
diff --git a/lms/djangoapps/courseware/tests/test_videoalpha_mongo.py b/lms/djangoapps/courseware/tests/test_video_mongo.py
similarity index 90%
rename from lms/djangoapps/courseware/tests/test_videoalpha_mongo.py
rename to lms/djangoapps/courseware/tests/test_video_mongo.py
index 38b2b6fb8dc7d7aa6395c29a0b5bb0fb4911643c..2927bfc37a2773eb9f3f737d40a510519ab0b161 100644
--- a/lms/djangoapps/courseware/tests/test_videoalpha_mongo.py
+++ b/lms/djangoapps/courseware/tests/test_video_mongo.py
@@ -2,22 +2,22 @@
 """Video xmodule tests in mongo."""
 
 from . import BaseTestXmodule
-from .test_videoalpha_xml import SOURCE_XML
+from .test_video_xml import SOURCE_XML
 from django.conf import settings
-from xmodule.videoalpha_module import _create_youtube_string
+from xmodule.video_module import _create_youtube_string
 
 
 class TestVideo(BaseTestXmodule):
     """Integration tests: web client + mongo."""
 
-    CATEGORY = "videoalpha"
+    CATEGORY = "video"
     DATA = SOURCE_XML
     MODEL_DATA = {
         'data': DATA
     }
 
     def setUp(self):
-        # Since the VideoAlphaDescriptor changes `self._model_data`,
+        # Since the VideoDescriptor changes `self._model_data`,
         # we need to instantiate `self.item_module` through
         # `self.item_descriptor` rather than directly constructing it
         super(TestVideo, self).setUp()
@@ -40,7 +40,7 @@ class TestVideo(BaseTestXmodule):
                 ]).pop(),
             404)
 
-    def test_videoalpha_constructor(self):
+    def test_video_constructor(self):
         """Make sure that all parameters extracted correclty from xml"""
 
         context = self.item_module.get_html()
@@ -74,7 +74,7 @@ class TestVideoNonYouTube(TestVideo):
     """Integration tests: web client + mongo."""
 
     DATA = """
-        <videoalpha show_captions="true"
+        <video show_captions="true"
         display_name="A Name"
         sub="a_sub_file.srt.sjson"
         start_time="01:00:03" end_time="01:00:10"
@@ -82,13 +82,13 @@ class TestVideoNonYouTube(TestVideo):
             <source src="example.mp4"/>
             <source src="example.webm"/>
             <source src="example.ogv"/>
-        </videoalpha>
+        </video>
     """
     MODEL_DATA = {
         'data': DATA
     }
 
-    def test_videoalpha_constructor(self):
+    def test_video_constructor(self):
         """Make sure that if the 'youtube' attribute is omitted in XML, then
             the template generates an empty string for the YouTube streams.
         """
diff --git a/lms/djangoapps/courseware/tests/test_videoalpha_xml.py b/lms/djangoapps/courseware/tests/test_video_xml.py
similarity index 74%
rename from lms/djangoapps/courseware/tests/test_videoalpha_xml.py
rename to lms/djangoapps/courseware/tests/test_video_xml.py
index e83582e1316c23283333c37fd75b9c6c97f029a2..64dbe4057bd3ca5718a512ebba374704b2b8a261 100644
--- a/lms/djangoapps/courseware/tests/test_videoalpha_xml.py
+++ b/lms/djangoapps/courseware/tests/test_video_xml.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 # pylint: disable=W0212
 
-"""Test for VideoAlpha Xmodule functional logic.
+"""Test for Video Xmodule functional logic.
 These test data read from xml, not from mongo.
 
 We have a ModuleStoreTestCase class defined in
@@ -20,14 +20,14 @@ import unittest
 
 from django.conf import settings
 
-from xmodule.videoalpha_module import (
-    VideoAlphaDescriptor, _create_youtube_string)
+from xmodule.video_module import (
+    VideoDescriptor, _create_youtube_string)
 from xmodule.modulestore import Location
 from xmodule.tests import get_test_system, LogicTest
 
 
 SOURCE_XML = """
-    <videoalpha show_captions="true"
+    <video show_captions="true"
     display_name="A Name"
     youtube="0.75:jNCf2gIqpeE,1.0:ZwkTiUPN0mg,1.25:rsq9auxASqI,1.50:kMyNdzVHHgg"
     sub="a_sub_file.srt.sjson"
@@ -36,12 +36,12 @@ SOURCE_XML = """
         <source src="example.mp4"/>
         <source src="example.webm"/>
         <source src="example.ogv"/>
-    </videoalpha>
+    </video>
 """
 
 
-class VideoAlphaFactory(object):
-    """A helper class to create videoalpha modules with various parameters
+class VideoFactory(object):
+    """A helper class to create video modules with various parameters
     for testing.
     """
 
@@ -50,28 +50,28 @@ class VideoAlphaFactory(object):
 
     @staticmethod
     def create():
-        """Method return VideoAlpha Xmodule instance."""
-        location = Location(["i4x", "edX", "videoalpha", "default",
+        """Method return Video Xmodule instance."""
+        location = Location(["i4x", "edX", "video", "default",
                              "SampleProblem1"])
-        model_data = {'data': VideoAlphaFactory.sample_problem_xml_youtube,
+        model_data = {'data': VideoFactory.sample_problem_xml_youtube,
                       'location': location}
 
         system = get_test_system()
         system.render_template = lambda template, context: context
 
-        descriptor = VideoAlphaDescriptor(system, model_data)
+        descriptor = VideoDescriptor(system, model_data)
 
         module = descriptor.xmodule(system)
 
         return module
 
 
-class VideoAlphaModuleUnitTest(unittest.TestCase):
-    """Unit tests for VideoAlpha Xmodule."""
+class VideoModuleUnitTest(unittest.TestCase):
+    """Unit tests for Video Xmodule."""
 
-    def test_videoalpha_get_html(self):
+    def test_video_get_html(self):
         """Make sure that all parameters extracted correclty from xml"""
-        module = VideoAlphaFactory.create()
+        module = VideoFactory.create()
         module.runtime.render_template = lambda template, context: context
 
         sources = {
@@ -98,18 +98,18 @@ class VideoAlphaModuleUnitTest(unittest.TestCase):
 
         self.assertEqual(module.get_html(), expected_context)
 
-    def test_videoalpha_instance_state(self):
-        module = VideoAlphaFactory.create()
+    def test_video_instance_state(self):
+        module = VideoFactory.create()
 
         self.assertDictEqual(
             json.loads(module.get_instance_state()),
             {'position': 0})
 
 
-class VideoAlphaModuleLogicTest(LogicTest):
-    """Tests for logic of VideoAlpha Xmodule."""
+class VideoModuleLogicTest(LogicTest):
+    """Tests for logic of Video Xmodule."""
 
-    descriptor_class = VideoAlphaDescriptor
+    descriptor_class = VideoDescriptor
 
     raw_model_data = {
         'data': '<video />'
@@ -117,23 +117,23 @@ class VideoAlphaModuleLogicTest(LogicTest):
 
     def test_parse_time(self):
         """Ensure that times are parsed correctly into seconds."""
-        output = VideoAlphaDescriptor._parse_time('00:04:07')
+        output = VideoDescriptor._parse_time('00:04:07')
         self.assertEqual(output, 247)
 
     def test_parse_time_none(self):
         """Check parsing of None."""
-        output = VideoAlphaDescriptor._parse_time(None)
+        output = VideoDescriptor._parse_time(None)
         self.assertEqual(output, '')
 
     def test_parse_time_empty(self):
         """Check parsing of the empty string."""
-        output = VideoAlphaDescriptor._parse_time('')
+        output = VideoDescriptor._parse_time('')
         self.assertEqual(output, '')
 
     def test_parse_youtube(self):
         """Test parsing old-style Youtube ID strings into a dict."""
         youtube_str = '0.75:jNCf2gIqpeE,1.00:ZwkTiUPN0mg,1.25:rsq9auxASqI,1.50:kMyNdzVHHgg'
-        output = VideoAlphaDescriptor._parse_youtube(youtube_str)
+        output = VideoDescriptor._parse_youtube(youtube_str)
         self.assertEqual(output, {'0.75': 'jNCf2gIqpeE',
                                   '1.00': 'ZwkTiUPN0mg',
                                   '1.25': 'rsq9auxASqI',
@@ -145,7 +145,7 @@ class VideoAlphaModuleLogicTest(LogicTest):
         empty string.
         """
         youtube_str = '0.75:jNCf2gIqpeE'
-        output = VideoAlphaDescriptor._parse_youtube(youtube_str)
+        output = VideoDescriptor._parse_youtube(youtube_str)
         self.assertEqual(output, {'0.75': 'jNCf2gIqpeE',
                                   '1.00': '',
                                   '1.25': '',
@@ -158,8 +158,8 @@ class VideoAlphaModuleLogicTest(LogicTest):
         youtube_str = '1.00:p2Q6BrNhdh8'
         youtube_str_hack = '1.0:p2Q6BrNhdh8'
         self.assertEqual(
-            VideoAlphaDescriptor._parse_youtube(youtube_str),
-            VideoAlphaDescriptor._parse_youtube(youtube_str_hack)
+            VideoDescriptor._parse_youtube(youtube_str),
+            VideoDescriptor._parse_youtube(youtube_str_hack)
         )
 
     def test_parse_youtube_empty(self):
@@ -167,7 +167,7 @@ class VideoAlphaModuleLogicTest(LogicTest):
         Some courses have empty youtube attributes, so we should handle
         that well.
         """
-        self.assertEqual(VideoAlphaDescriptor._parse_youtube(''),
+        self.assertEqual(VideoDescriptor._parse_youtube(''),
                          {'0.75': '',
                           '1.00': '',
                           '1.25': '',