diff --git a/platypush/backend/http/static/css/video.omxplayer.css b/platypush/backend/http/static/css/video.omxplayer.css
index 4c8d6efd0..c0cff1dfb 100644
--- a/platypush/backend/http/static/css/video.omxplayer.css
+++ b/platypush/backend/http/static/css/video.omxplayer.css
@@ -1,6 +1,6 @@
 #video-search {
     max-width: 60em;
-    margin: 3em auto 1em auto;
+    margin: 1em auto;
 }
 
     #video-search input[type=text] {
@@ -11,3 +11,64 @@ form#video-ctrl {
     text-align: center;
 }
 
+#video-seeker-container {
+    margin-top: 0.5em;
+    margin-bottom: 1em;
+}
+
+#video-volume-ctrl-container {
+    margin-top: 1em;
+}
+
+#video-results {
+    padding: 1.5rem 1.5rem 0 .5rem;
+    background: #f8f8f8;
+}
+
+    .video-result {
+        padding: 5px;
+        letter-spacing: .1rem;
+        line-height: 3.3rem;
+        cursor: pointer;
+    }
+
+        .video-result.selected {
+            background-color: #c8ffd0 !important;
+        }
+
+        .video-result:hover {
+            background-color: #daf8e2 !important;
+        }
+
+        .video-result:nth-child(odd) {
+            background-color: #f2f2f2;
+        }
+
+        .video-result.active {
+            height: 4rem;
+            padding-top: 1.5rem;
+            font-size: 1.7rem;
+            border-radius: 10px;
+            animation: active-track 5s;
+            -moz-animation: active-track 5s infinite;
+            -webkit-animation: active-track 5s infinite;
+        }
+
+            @keyframes active-track {
+                0% { background: #d4ffe3; }
+                50% { background: #9cdfb0; }
+                100% { background: #d4ffe3; }
+            }
+
+            @-moz-keyframes active-track {
+                0% { background: #d4ffe3; }
+                50% { background: #9cdfb0; }
+                100% { background: #d4ffe3; }
+            }
+
+            @-webkit-keyframes active-track {
+                0% { background: #d4ffe3; }
+                50% { background: #9cdfb0; }
+                100% { background: #d4ffe3; }
+            }
+
diff --git a/platypush/backend/http/static/js/music.mpd.js b/platypush/backend/http/static/js/music.mpd.js
index 7613e7169..70f94d3d7 100644
--- a/platypush/backend/http/static/js/music.mpd.js
+++ b/platypush/backend/http/static/js/music.mpd.js
@@ -521,26 +521,11 @@ $(document).ready(function() {
             );
         });
 
-        $volumeCtrl.on('mousedown', function(event) {
+        $volumeCtrl.on('mousedown touchstart', function(event) {
             prevVolume = $(this).val();
         });
 
-        $volumeCtrl.on('mouseup', function(event) {
-            execute(
-                {
-                    type: 'request',
-                    action: 'music.mpd.setvol',
-                    args: { vol: $(this).val() }
-                },
-
-                onSuccess=undefined,
-                onError = function() {
-                    $volumeCtrl.val(prevVolume);
-                }
-            );
-        });
-
-        $volumeCtrl.on('mouseup', function(event) {
+        $volumeCtrl.on('mouseup touchend', function(event) {
             execute(
                 {
                     type: 'request',
diff --git a/platypush/backend/http/static/js/video.omxplayer.js b/platypush/backend/http/static/js/video.omxplayer.js
index dd7c9e8c7..d19465fd7 100644
--- a/platypush/backend/http/static/js/video.omxplayer.js
+++ b/platypush/backend/http/static/js/video.omxplayer.js
@@ -1,41 +1,66 @@
 $(document).ready(function() {
     var $container = $('#video-container'),
         $searchForm = $('#video-search'),
-        $ctrlForm = $('#video-ctrl');
+        $videoResults = $('#video-results'),
+        $volumeCtrl = $('#video-volume-ctrl'),
+        $ctrlForm = $('#video-ctrl'),
+        prevVolume = undefined;
+
+    var updateVideoResults = function(videos) {
+        $videoResults.html('');
+        for (var video of videos) {
+            var $videoResult = $('<div></div>')
+                .addClass('video-result')
+                .attr('data-url', video['url'])
+                .html('title' in video ? video['title'] : video['url']);
+
+            $videoResult.appendTo($videoResults);
+        }
+    };
 
     var initBindings = function() {
         $searchForm.on('submit', function(event) {
-            var formData = $(this).serializeArray().reduce(function(obj, item) {
-                var value = item.value.trim();
-                if (value.length > 0) {
-                    obj[item.name] = item.value;
-                }
+            var $input = $(this).find('input[name=video-search-text]');
+            var resource = $input.val();
+            var request = {}
+            var onSuccess = function() {};
+            var onError = function() {};
+            var onComplete = function() {
+                $input.prop('disabled', false);
+            };
 
-                return obj;
-            }, {});
+            $input.prop('disabled', true);
+            $videoResults.text('Searching...');
 
-            execute(
-                {
+            if (resource.match(new RegExp('^https?://')) ||
+                resource.match(new RegExp('^file://'))) {
+                var videos = [{ url: resource }];
+                updateVideoResults(videos);
+
+                request = {
                     type: 'request',
-                    action: 'video.omxplayer.stop',
-                },
+                    action: 'video.omxplayer.play',
+                    args: { resource: resource }
+                };
+            } else {
+                request = {
+                    type: 'request',
+                    action: 'video.omxplayer.youtube_search',
+                    args: { query: resource }
+                };
 
-                function() {
-                    execute(
-                        {
-                            type: 'request',
-                            action: 'video.omxplayer.play',
-                            args: formData,
-                        }
-                    )
-                }
-            );
+                onSuccess = function(response) {
+                    var videos = response.response.output;
+                    updateVideoResults(videos);
+                };
+            }
 
+            execute(request, onSuccess, onError, onComplete)
             return false;
         });
 
         $ctrlForm.on('submit', function() { return false; });
-        $ctrlForm.find('button[data-action]').on('click', function(evt) {
+        $ctrlForm.find('button[data-action]').on('click touch', function(evt) {
             var action = $(this).data('action');
             var $btn = $(this);
 
@@ -46,6 +71,54 @@ $(document).ready(function() {
                 }
             );
         });
+
+        $volumeCtrl.on('mousedown touchstart', function(event) {
+            prevVolume = $(this).val();
+        });
+
+        $volumeCtrl.on('mouseup touchend', function(event) {
+            execute(
+                {
+                    type: 'request',
+                    action: 'video.omxplayer.set_volume',
+                    args: { volume: $(this).val() }
+                },
+
+                onSuccess=undefined,
+                onError = function() {
+                    $volumeCtrl.val(prevVolume);
+                }
+            );
+        });
+
+        $videoResults.on('click touch', '.video-result', function(evt) {
+            var results = $videoResults.html();
+            var $item = $(this);
+            if (!$item.hasClass('selected')) {
+                $item.siblings().removeClass('selected');
+                $item.addClass('selected');
+                return false;
+            }
+
+            $videoResults.text('Loading video...');
+            execute(
+                {
+                    type: 'request',
+                    action: 'video.omxplayer.play',
+                    args: { resource: $item.data('url') },
+                },
+
+                function() {
+                    $videoResults.html(results);
+                    $item.siblings().removeClass('active');
+                    $item.addClass('active');
+                },
+
+                function() {
+                    $videoResults.html(results);
+                },
+            );
+        });
     };
 
     var init = function() {
diff --git a/platypush/backend/http/templates/plugins/video.omxplayer.html b/platypush/backend/http/templates/plugins/video.omxplayer.html
index 3d4ec3aac..e541972c7 100644
--- a/platypush/backend/http/templates/plugins/video.omxplayer.html
+++ b/platypush/backend/http/templates/plugins/video.omxplayer.html
@@ -4,14 +4,14 @@
 <div class="row" id="video-container">
     <form action="#" id="video-search">
         <div class="row">
-            <label for="resource">
-                Supported formats: <tt>file://[path]</tt>, <tt>https://www.youtube.com/?v=[video_id]</tt>
+            <label for="video-search-text">
+                Supported formats: <tt>file://[path]</tt>, <tt>https://www.youtube.com/?v=[video_id]</tt>, or free text search
             </label>
         </div>
 
         <div class="row">
             <div class="eleven columns">
-                <input type="text" name="resource" placeholder="Video URL">
+                <input type="text" name="video-search-text" placeholder="Search query or video URL">
             </div>
             <div class="one column">
                 <button type="submit">
@@ -22,6 +22,14 @@
     </form>
 
     <form action="#" id="video-ctrl">
+        <!-- <div class="row"> -->
+        <!--     <div class="eight columns offset-by-two slider-container" id="video-seeker-container"> -->
+        <!--         <span class="seek-time" id="video-elapsed">-:--</span>&nbsp; -->
+        <!--         <input type="range" min="0" id="video-seeker" disabled="disabled" class="slider" style="width:75%"> -->
+        <!--         &nbsp;<span class="seek-time" id="video-length">-:--</span> -->
+        <!--     </div> -->
+        <!-- </div> -->
+
         <div class="row">
             <div class="ten columns offset-by-one">
                 <button data-action="previous">
@@ -52,6 +60,19 @@
                     <i class="fa fa-step-forward"></i>
                 </button>
             </div>
+        </div>
+
+        <div class="row">
+            <div class="eight columns offset-by-two slider-container" id="video-volume-ctrl-container">
+                <i class="fa fa-volume-down"></i> &nbsp;
+                <input type="range" min="0" max="100" value="100" id="video-volume-ctrl" class="slider" style="width:80%">
+                &nbsp; <i class="fa fa-volume-up"></i>
+            </div>
+        </div>
     </form>
+
+    <div class="row" id="video-results-container">
+        <div id="video-results"></div>
+    </div>
 </div>
 
diff --git a/platypush/plugins/video/omxplayer.py b/platypush/plugins/video/omxplayer.py
index bec12148f..96df27f8e 100644
--- a/platypush/plugins/video/omxplayer.py
+++ b/platypush/plugins/video/omxplayer.py
@@ -30,6 +30,15 @@ class VideoOmxplayerPlugin(Plugin):
 
         logging.info('Playing {}'.format(resource))
 
+        if self.player:
+            try:
+                self.player.stop()
+                self.player = None
+            except Exception as e:
+                logging.exception(e)
+                logging.warning('Unable to stop a previously running instance ' +
+                                'of OMXPlayer, trying to play anyway')
+
         try:
             self.player = OMXPlayer(resource, args=self.args)
             self._init_player_handlers()
@@ -145,29 +154,40 @@ class VideoOmxplayerPlugin(Plugin):
                 'state': PlayerState.STOP.value
             }))
 
+    def on_play(self):
+        def _f(player):
+            self.bus.post(VideoPlayEvent(video=self.player.get_source()))
+        return _f
+
+    def on_pause(self):
+        def _f(player):
+            self.bus.post(VideoPauseEvent(video=self.player.get_source()))
+        return _f
+
+    def on_stop(self):
+        def _f(player):
+            self.bus.post(VideoStopEvent())
+        return _f
+
+
     def _init_player_handlers(self):
         if not self.player:
             return
 
-        self.player.playEvent += lambda _: \
-            self.bus.post(VideoPlayEvent(video=self.player.get_source()))
-
-        self.player.pauseEvent += lambda _: \
-            self.bus.post(VideoPauseEvent(video=self.player.get_source()))
-
-        self.player.stopEvent += lambda _: \
-            self.bus.post(VideoStopEvent())
+        self.player.playEvent += self.on_play()
+        self.player.pauseEvent += self.on_pause()
+        self.player.stopEvent += self.on_stop()
 
     def youtube_search_and_play(self, query):
-        self.videos_queue = self.youtube_search(query)
+        self.videos_queue = self.youtube_search(query).output
         ret = None
 
         while self.videos_queue:
-            url = self.videos_queue.pop(0)
-            logging.info('Playing {}'.format(url))
+            video = self.videos_queue.pop(0)
+            logging.info('Playing "{}" from [{}]'.format(video['url'], video['title']))
 
             try:
-                ret = self.play(url)
+                ret = self.play(video['url'])
                 break
             except Exception as e:
                 logging.exception(e)
@@ -186,12 +206,15 @@ class VideoOmxplayerPlugin(Plugin):
         for vid in soup.findAll(attrs={'class':'yt-uix-tile-link'}):
             m = re.match('(/watch\?v=[^&]+)', vid['href'])
             if m:
-                results.append('https://www.youtube.com' + m.group(1))
+                results.append({
+                    'url': 'https://www.youtube.com' + m.group(1),
+                    'title': vid['title'],
+                })
 
         logging.info('{} YouTube video results for the search query "{}"'
                      .format(len(results), query))
 
-        return results
+        return Response(output=results)
 
 
     @classmethod