diff --git a/includes/utils.php b/includes/utils.php
index 35b11b3..0b407a3 100644
--- a/includes/utils.php
+++ b/includes/utils.php
@@ -242,6 +242,8 @@
             case 'flvp': return "$url.flvp";
             case 'flv' : return "$url.flv";
             case 'mp4' : return "$url.mp4";
+            case 'ogv' : return "$url.ogv";
+            case 'webm': return "$url.webm";
         }
     // No more dsmyth filters, so return the URL no matter what the browser is.
         return $url;
diff --git a/modules/stream/handler.pl b/modules/stream/handler.pl
index 9015c62..ec48cc4 100755
--- a/modules/stream/handler.pl
+++ b/modules/stream/handler.pl
@@ -33,6 +33,14 @@
     elsif ($ENV{'REQUEST_URI'} =~ /\.mp4$/i) {
         require "modules/$Path[0]/stream_mp4.pl";
     }
+# HTML5 video/ogv
+    elsif ($ENV{'REQUEST_URI'} =~ /\.ogv$/i) {
+        require "modules/$Path[0]/stream_ogv.pl";
+    }
+# HTML5 video/webm
+    elsif ($ENV{'REQUEST_URI'} =~ /\.webm$/i) {
+        require "modules/$Path[0]/stream_webm.pl";
+    }
 # Raw file?
     else {
         require "modules/$Path[0]/stream_raw.pl";
diff --git a/modules/stream/stream_ogv.pl b/modules/stream/stream_ogv.pl
new file mode 100755
index 0000000..51e02f4
--- /dev/null
+++ b/modules/stream/stream_ogv.pl
@@ -0,0 +1,158 @@
+#!/usr/bin/perl
+#
+# MythWeb Streaming/Download module
+#
+# @url       $URL$
+# @date      $Date$
+# @version   $Revision$
+# @author    $Author$
+#
+
+    use POSIX qw(ceil floor);
+
+# round to the nearest even integer
+    sub round_even {
+        my ($in) = @_;
+        my $n = floor($in);
+        return ($n % 2 == 0) ? $n : ceil($in);
+    }
+
+    our $ffmpeg_pid;
+    our $ffmpeg_pgid;
+
+# Shutdown cleanup, of various types
+    $ffmpeg_pgid = setpgrp(0,0);
+    $SIG{'TERM'} = \&shutdown_handler;
+    $SIG{'PIPE'} = \&shutdown_handler;
+    END {
+        shutdown_handler();
+    }
+    sub shutdown_handler {
+        kill(1, $ffmpeg_pid) if ($ffmpeg_pid);
+        kill(-1, $ffmpeg_pgid) if ($ffmpeg_pgid);
+    }
+
+# Find ffmpeg
+    $ffmpeg = '';
+    foreach my $path (split(/:/, $ENV{'PATH'}.':/usr/local/bin:/usr/bin'), '.') {
+        if (-e "$path/mythffmpeg") {
+            $ffmpeg = "$path/mythffmpeg";
+            last;
+        }
+        if (-e "$path/ffmpeg") {
+            $ffmpeg = "$path/ffmpeg";
+            last;
+        }
+        elsif ($^O eq 'darwin' && -e "$path/ffmpeg.app") {
+            $ffmpeg = "$path/ffmpeg.app";
+            last;
+        }
+    }
+
+# Load some conversion settings from the database
+    $sh = $dbh->prepare('SELECT data FROM settings WHERE value=? AND hostname IS NULL');
+    $sh->execute('WebFLV_w');
+    my ($width)    = $sh->fetchrow_array;
+    $sh->execute('WebFLV_vb');
+    my ($vbitrate) = $sh->fetchrow_array;
+    $sh->execute('WebFLV_ab');
+    my ($abitrate) = $sh->fetchrow_array;
+    $sh->finish();
+# auto-detect height based on aspect ratio
+    $sh = $dbh->prepare('SELECT data FROM recordedmarkup WHERE chanid=? ' .
+                        'AND starttime=FROM_UNIXTIME(?) AND type=30 ' .
+                        'AND data IS NOT NULL ORDER BY mark LIMIT 1');
+    $sh->execute($chanid,$starttime);
+    $x = $sh->fetchrow_array;           # type = 30
+    $sh->finish();
+
+    $sh = $dbh->prepare('SELECT data FROM recordedmarkup WHERE chanid=? ' .
+                        'AND starttime=FROM_UNIXTIME(?) AND type=31 ' .
+                        'AND data IS NOT NULL ORDER BY mark LIMIT 1');
+    $sh->execute($chanid,$starttime);
+    $y = $sh->fetchrow_array if ($x);   # type = 31
+    $sh->finish();
+
+    if (!$x || !$y || $x <= 720) {      # <=720 means SD 
+        $sh = $dbh->prepare('SELECT recordedmarkup.type, ' .
+               'recordedmarkup.data '.
+               'FROM recordedmarkup ' .
+               'WHERE recordedmarkup.chanid = ? ' .
+               'AND recordedmarkup.starttime = FROM_UNIXTIME(?)  ' .
+               'AND recordedmarkup.type IN (10, 11, 12, 13, 14) ' .
+               'GROUP BY recordedmarkup.type  ' .
+               'ORDER BY SUM((SELECT IFNULL(rm.mark, recordedmarkup.mark) ' .
+               '   FROM recordedmarkup AS rm ' .
+               '   WHERE rm.chanid = recordedmarkup.chanid ' .
+               '   AND rm.starttime = recordedmarkup.starttime ' .
+               '   AND rm.type IN (10, 11, 12, 13, 14)  ' .
+               '   AND rm.mark > recordedmarkup.mark ' .
+               '   ORDER BY rm.mark ASC LIMIT 1)- recordedmarkup.mark) DESC ' .
+               'LIMIT 1'); 
+        $sh->execute($chanid,$starttime); 
+        $aspect = $sh->fetchrow_hashref; 
+        $sh->finish(); 
+
+        if( $aspect->{'type'} == 10 ) { 
+            $x = $y = 1; 
+        } elsif( $aspect->{'type'}== 11 ) { 
+            $x = 4; $y = 3; 
+        } elsif( $aspect->{'type'}== 12 ) { 
+            $x = 16; $y = 9; 
+        } elsif( $aspect->{'type'}== 13 ) { 
+            $x = 2.21; $y = 1; 
+        } elsif( $aspect->{'type'}== 14 ) { 
+            $x = $aspect->{'data'}; $y = 10000; 
+        } else { 
+            $x = 4; $y = 3; 
+        } 
+    } 
+    $height = round_even($width * ($y/$x)); 
+
+    $width    = 320 unless ($width    && $width    > 1);
+    $height   = 240 unless ($height   && $height   > 1);
+    $vbitrate = 256 unless ($vbitrate && $vbitrate > 1);
+    $abitrate = 64  unless ($abitrate && $abitrate > 1);
+
+    my $ffmpeg_command = $ffmpeg
+                        .' -y'
+                        .' -i '.shell_escape($filename)
+                        .' -s '.shell_escape("${width}x${height}")
+                        .' -g 30'
+                        .' -r 24'
+                        .' -f ogg'
+                        .' -acodec libvorbis'
+                        .' -vcodec libtheora'
+                        .' -deinterlace'
+                        .' -async 2'
+                        .' -ac 2'
+                        .' -ar 11025'
+                        .' -ab '.shell_escape("${abitrate}k")
+                        .' -b '.shell_escape("${vbitrate}k")
+                        .' /dev/stdout 2>/dev/null |';
+
+# Print the movie
+    $ffmpeg_pid = open(DATA, $ffmpeg_command);
+    unless ($ffmpeg_pid) {
+        print header(),
+                "Can't do ffmpeg: $!\n${ffmpeg_command}";
+        exit;
+    }
+    # Guess the filesize based on duration and bitrate. This allows for progressive download behavior
+    my $lengthSec;
+    $dur = `$ffmpeg -i $filename 2>&1 | grep "Duration" | cut -d ' ' -f 4 | sed s/,//`;
+    if ($dur && $dur =~ /\d*:\d*:.*/) {
+        @times = split(':',$dur);
+        $lengthSec = $times[0]*3600+$times[1]*60+$times[2];
+        $size = int(1.05*$lengthSec*($vbitrate*1024+$abitrate*1024)/8);
+        print header(-type => 'video/ogg','Content-Length' => $size);
+    } else {
+        print header(-type => 'video/ogg');
+    }
+
+    while (<DATA>) {
+        print $_;
+    }
+    close DATA;
+
+    1;
diff --git a/modules/stream/stream_webm.pl b/modules/stream/stream_webm.pl
new file mode 100755
index 0000000..fb10ebe
--- /dev/null
+++ b/modules/stream/stream_webm.pl
@@ -0,0 +1,158 @@
+#!/usr/bin/perl
+#
+# MythWeb Streaming/Download module
+#
+# @url       $URL$
+# @date      $Date$
+# @version   $Revision$
+# @author    $Author$
+#
+
+    use POSIX qw(ceil floor);
+
+# round to the nearest even integer
+    sub round_even {
+        my ($in) = @_;
+        my $n = floor($in);
+        return ($n % 2 == 0) ? $n : ceil($in);
+    }
+
+    our $ffmpeg_pid;
+    our $ffmpeg_pgid;
+
+# Shutdown cleanup, of various types
+    $ffmpeg_pgid = setpgrp(0,0);
+    $SIG{'TERM'} = \&shutdown_handler;
+    $SIG{'PIPE'} = \&shutdown_handler;
+    END {
+        shutdown_handler();
+    }
+    sub shutdown_handler {
+        kill(1, $ffmpeg_pid) if ($ffmpeg_pid);
+        kill(-1, $ffmpeg_pgid) if ($ffmpeg_pgid);
+    }
+
+# Find ffmpeg
+    $ffmpeg = '';
+    foreach my $path (split(/:/, $ENV{'PATH'}.':/usr/local/bin:/usr/bin'), '.') {
+        if (-e "$path/mythffmpeg") {
+            $ffmpeg = "$path/mythffmpeg";
+            last;
+        }
+        if (-e "$path/ffmpeg") {
+            $ffmpeg = "$path/ffmpeg";
+            last;
+        }
+        elsif ($^O eq 'darwin' && -e "$path/ffmpeg.app") {
+            $ffmpeg = "$path/ffmpeg.app";
+            last;
+        }
+    }
+
+# Load some conversion settings from the database
+    $sh = $dbh->prepare('SELECT data FROM settings WHERE value=? AND hostname IS NULL');
+    $sh->execute('WebFLV_w');
+    my ($width)    = $sh->fetchrow_array;
+    $sh->execute('WebFLV_vb');
+    my ($vbitrate) = $sh->fetchrow_array;
+    $sh->execute('WebFLV_ab');
+    my ($abitrate) = $sh->fetchrow_array;
+    $sh->finish();
+# auto-detect height based on aspect ratio
+    $sh = $dbh->prepare('SELECT data FROM recordedmarkup WHERE chanid=? ' .
+                        'AND starttime=FROM_UNIXTIME(?) AND type=30 ' .
+                        'AND data IS NOT NULL ORDER BY mark LIMIT 1');
+    $sh->execute($chanid,$starttime);
+    $x = $sh->fetchrow_array;           # type = 30
+    $sh->finish();
+
+    $sh = $dbh->prepare('SELECT data FROM recordedmarkup WHERE chanid=? ' .
+                        'AND starttime=FROM_UNIXTIME(?) AND type=31 ' .
+                        'AND data IS NOT NULL ORDER BY mark LIMIT 1');
+    $sh->execute($chanid,$starttime);
+    $y = $sh->fetchrow_array if ($x);   # type = 31
+    $sh->finish();
+
+    if (!$x || !$y || $x <= 720) {      # <=720 means SD 
+        $sh = $dbh->prepare('SELECT recordedmarkup.type, ' .
+               'recordedmarkup.data '.
+               'FROM recordedmarkup ' .
+               'WHERE recordedmarkup.chanid = ? ' .
+               'AND recordedmarkup.starttime = FROM_UNIXTIME(?)  ' .
+               'AND recordedmarkup.type IN (10, 11, 12, 13, 14) ' .
+               'GROUP BY recordedmarkup.type  ' .
+               'ORDER BY SUM((SELECT IFNULL(rm.mark, recordedmarkup.mark) ' .
+               '   FROM recordedmarkup AS rm ' .
+               '   WHERE rm.chanid = recordedmarkup.chanid ' .
+               '   AND rm.starttime = recordedmarkup.starttime ' .
+               '   AND rm.type IN (10, 11, 12, 13, 14)  ' .
+               '   AND rm.mark > recordedmarkup.mark ' .
+               '   ORDER BY rm.mark ASC LIMIT 1)- recordedmarkup.mark) DESC ' .
+               'LIMIT 1'); 
+        $sh->execute($chanid,$starttime); 
+        $aspect = $sh->fetchrow_hashref; 
+        $sh->finish(); 
+
+        if( $aspect->{'type'} == 10 ) { 
+            $x = $y = 1; 
+        } elsif( $aspect->{'type'}== 11 ) { 
+            $x = 4; $y = 3; 
+        } elsif( $aspect->{'type'}== 12 ) { 
+            $x = 16; $y = 9; 
+        } elsif( $aspect->{'type'}== 13 ) { 
+            $x = 2.21; $y = 1; 
+        } elsif( $aspect->{'type'}== 14 ) { 
+            $x = $aspect->{'data'}; $y = 10000; 
+        } else { 
+            $x = 4; $y = 3; 
+        } 
+    } 
+    $height = round_even($width * ($y/$x)); 
+
+    $width    = 320 unless ($width    && $width    > 1);
+    $height   = 240 unless ($height   && $height   > 1);
+    $vbitrate = 256 unless ($vbitrate && $vbitrate > 1);
+    $abitrate = 64  unless ($abitrate && $abitrate > 1);
+
+    my $ffmpeg_command = $ffmpeg
+                        .' -y'
+                        .' -i '.shell_escape($filename)
+                        .' -s '.shell_escape("${width}x${height}")
+                        .' -g 30'
+                        .' -r 24'
+                        .' -f webm'
+                        .' -acodec libvorbis'
+                        .' -vcodec libvpx'
+                        .' -deinterlace'
+                        .' -async 2'
+                        .' -ac 2'
+                        .' -ar 11025'
+                        .' -ab '.shell_escape("${abitrate}k")
+                        .' -b '.shell_escape("${vbitrate}k")
+                        .' /dev/stdout 2>/dev/null |';
+
+# Print the movie
+    $ffmpeg_pid = open(DATA, $ffmpeg_command);
+    unless ($ffmpeg_pid) {
+        print header(),
+                "Can't do ffmpeg: $!\n${ffmpeg_command}";
+        exit;
+    }
+    # Guess the filesize based on duration and bitrate. This allows for progressive download behavior
+    my $lengthSec;
+    $dur = `$ffmpeg -i $filename 2>&1 | grep "Duration" | cut -d ' ' -f 4 | sed s/,//`;
+    if ($dur && $dur =~ /\d*:\d*:.*/) {
+        @times = split(':',$dur);
+        $lengthSec = $times[0]*3600+$times[1]*60+$times[2];
+        $size = int(1.05*$lengthSec*($vbitrate*1024+$abitrate*1024)/8);
+        print header(-type => 'video/webm','Content-Length' => $size);
+    } else {
+        print header(-type => 'video/webm');
+    }
+
+    while (<DATA>) {
+        print $_;
+    }
+    close DATA;
+
+    1;
diff --git a/modules/tv/tmpl/default/detail.php b/modules/tv/tmpl/default/detail.php
index cdd8093..1183c8c 100644
--- a/modules/tv/tmpl/default/detail.php
+++ b/modules/tv/tmpl/default/detail.php
@@ -649,6 +649,10 @@
 
             <div class="x-pixmap">
 <?php   if (setting('WebFLV_on')) { ?>
+          <!--Embed HTML5 video if supported-->
+            <video controls="controls" preload="none" width="<?php echo $flv_w ?>" height="<?php echo $flv_h ?>" poster="<?php echo $program->thumb_url($flv_w,0) ?>">
+                <source src="<?php echo video_url($program, 'ogv'); ?>" type="video/ogg" />
+                <source src="<?php echo video_url($program, 'webm'); ?>" type="video/webm" />
 <?php       if (file_exists('js/libs/flowplayer/flowplayer.swf')) { ?>
 
 
@@ -793,6 +797,8 @@
                         </embed>
                     </object>
                     </noscript>
+          <!--Close HTML5 video tag-->
+            </video>
 <?php       } ?>
 <?php   } else { ?>
                 <a href="<?php echo $program->url ?>" title="<?php echo t('Direct Download') ?>"
diff --git a/mythweb.conf.apache b/mythweb.conf.apache
index c2a4f00..d7dade2 100644
--- a/mythweb.conf.apache
+++ b/mythweb.conf.apache
@@ -184,6 +184,10 @@
     # those are, so we should tell it.
         AddType video/nuppelvideo   .nuv
 
+    # Support HTML5 video formats which can be encoded and streamed "on-the-fly"
+        AddType video/ogg           .ogv .ogg
+        AddType video/webm          .webm
+
     # Specify the MIME type for favicon.ico in case the server configuration
     # doesn't or in case the server configuration uses the IANA-approved MIME type
     # (image/vnd.microsoft.icon)--which most browsers won't recognize.
