Hack to make vipers-video-quicktags detect iPad and use HTML5 Video Tag

I use this WordPress plugin, vipers-video-quicktag, in a couple sites I maintain. I use it to display FLV video. I’ve found if I create .mp4 videos with the H.262 video and AAC audio codecs, it’ll play in the Flash player, as well as on iPhone, iPad and iPod. This is neat, a single video format that works on all 3.

Problem is, with vipers-video-quicktag, it doesn’t detect iPhone/iPod/iPad on the Flash video option and just tries to display it with the Flash player, which we all know doesn’t work on iPhone/iPod/iPad.

The trick is to detect iPhone/iPod/iPad and instead of putting in the Flash video, instead put in a HTML5 Video tag.

WordPress: http://wordpress.org/extend/plugins/vipers-video-quicktags/
Author’s Page: http://www.viper007bond.com/wordpress-plugins/vipers-video-quicktags/

If you know how to read a diff file, here’s how I hacked it in. Remember, this is only going to work universally, if your videos are .mp4 with H.264/AAC encoding.

# diff -Naur vipers-video-quicktags.php.orig vipers-video-quicktags.php
--- vipers-video-quicktags.php.orig     2010-05-23 22:15:11.000000000 -0700
+++ vipers-video-quicktags.php  2010-05-23 22:19:22.000000000 -0700
@@ -3663,7 +3663,9 @@
                //$content .= "// <![CDATA[\n";
 
                foreach ( $this->swfobjects as $objectid => $embed ) {
-                       $content .= '   swfobject.embedSWF("' . htmlspecialchars( $embed['url'] ) . '", "' . $objectid . '", "' . $embed['width'] . '", "' . $embed['height'] . '", "9", vvqexpressinstall, ';
+# dkhack, replace this line with HTML5 Video tag when it's iPhone, iPad, iPod:
+                       # $content .= ' swfobject.embedSWF("' . htmlspecialchars( $embed['url'] ) . '", "' . $objectid . '", "' . $embed['width'] . '", "' . $embed['height'] . '", "9", vvqexpressinstall, ';
+                       $content .= 'if ((navigator.userAgent.indexOf(\'iPhone\') != -1) || (navigator.userAgent.indexOf(\'iPod\') != -1) || (navigator.userAgent.indexOf(\'iPad\') != -1)) document.getElementById("'.$objectid.'").innerHTML = \'<video width="'.$embed['width'] .'" height="'.$embed['height'].'" poster="'.preg_replace("/\.[^\.]{3}$/", ".jpg",  $embed['flashvars']['file']).'" src="'. $embed['flashvars']['file'].'" controls />\'; else  swfobject.embedSWF("' . htmlspecialchars( $embed['url'] ) . '", "' . $objectid . '", "' . $embed['width'] . '", "' . $embed['height'] . '", "9", vvqexpressinstall, ';
 
                        if ( empty($embed['flashvars']) || !is_array($embed['flashvars']) ) {
                                $content .= 'vvqflashvars';

Basically, what it’s doing is detecting iPhone/iPod/iPad in JavaScript and writing this:

<video width="'710" height="400" poster="http://host.tld/path/to/video.jpg" src="http://host.tld/path/to/video.mp4" controls />

One more thing to note…. When I tested this with my iPad, it didn’t work at first. Something is wrong with the iPad – it doesn’t want to see the movie when it’s at it’s default location in WordPress after upload. Is there a 300 level redirect in there somewhere that iPad doesn’t like? Maybe something with .htaccess. Workaround: What fixed it for me was creating a new directory in my DOCUMENT_ROOT called “videos” and then I put symlinks in there to the physical files, and then used these http://host.tld/videos/my_video.mp4 URLs and it works fine.

Dave.

Make a Poster JPG for each MP4

Nifty command to take a list of MP4 videos and make a poster JPG for each one:

for i in `ls *.mp4`; do echo $i; j=`echo $i | sed -e 's/.mp4/.jpg/'`; echo $j; ffmpeg -i $i -r 1 -f image2 -t 1 $j; done

This takes each mp4 video in a directory and creates a .jpg for it. In the ffmpeg command, the -r 1 means 1 frame per second, and the -t 1 means stop after 1 second. The -f image2 means the output is an image.

This is useful when you have a bunch of videos to upload to say WordPress for use with, oh say, vipers-video-quicktags plugin that automatically looks for a file with the same name, but a .jpg extension, for the poster. In case it’s not obvious, the poster is the image that displays on a video before play.

Spirit Jailbreak for iPad

Download the Spirit Jailbreak here http://spiritjb.com/ run and presto, your iPad is JailBroken.

First problem, the MobileTerminal app in Cydia crashes. Good workaround: I already had the iSSH app installed from App Store. I think it was $10. I installed openSSH on my iPad from Cydia, then created a configuration in iSSH for localhost at 127.0.0.1. Now I can use iSSH as a Terminal, using username root and password alpine (first login). Works. I can also SSH to my iPad when my laptop and iPad are on the same WiFi network.

If you do this, make sure to change the default root password from alpine to something else. Don’t want some random person to break into your iPad when you’re on a public network. Also change the password for the “mobile” user:

Dave-Laptops-iPad:~ root# passwd
Changing password for root.
New password:
Retype new password:
Dave-Laptops-iPad:~ root# passwd mobile
Changing password for mobile.
New password:
Retype new password:

Stunnel can run multiple ips and certs in one instance

Apparently only the newer versions can do this, 4.15+, but the concept is simple:

setuid          = stunnel
setgid          = stunnel
debug           = 5
output          = /var/log/stunnel/stunnel.log
pid             = /var/run/stunnel/stunnel.pid
socket          = l:TCP_NODELAY=1
ciphers         = ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:!LOW:!SSLv2:!EXP:!eNULL
options         = NO_SSLv2

[https-site1]
accept          = 10.0.0.1:443
cert            = /etc/pki/tls/certs/site1.pem
connect         = 10.0.0.101:80
TIMEOUTclose    = 0

[https-site2]
accept          = 10.0.0.2:443
cert            = /etc/pki/tls/certs/site2.pem
connect         = 10.0.0.102:80
TIMEOUTclose    = 0

This is much better than running multiple instances of stunnel.

For what it’s worth, if you enable a log file, it’ll turn off sys logging, which is critical for extreme performance. Keep the debug level low. For https, disable v2 and set the cipher list the right way.

iPad HTML5 Video tag with div overlay with form not working

If you have a page that detects browser and feeds up the Flash version for browsers that’ll accept it and the HTML5 version for those that will take that, you may have noticed that trying to display a DIV over the top of the video renders that <form> inside to not work on the iPad. It’s like the Video tag is a black hole for user input.

One workaround is to change the visibility of the video tag to hidden”

<script language="javascript">
function toggleDivFlagForm() {
  if ( document.getElementById('divFlagForm').style.display == 'none' )
  {
     document.getElementById('divFlagForm').style.display = 'inline';
    document.getElementById('dVideo').style.display = 'none';
  }
  else
  {
     document.getElementById('divFlagForm').style.display = 'none';
    document.getElementById('dVideo').style.display = 'inline';
  }
}
</script>

http://www.koopman.me/test2.html

<html>
<head><title>Video test</title>
<script language="javascript">
function toggleDivFlagForm() {
  if ( document.getElementById('divFlagForm').style.display == 'none' )
  {
     document.getElementById('divFlagForm').style.display = 'inline';
    document.getElementById('dVideo').style.display = 'none';
  }
  else
  {
     document.getElementById('divFlagForm').style.display = 'none';
    document.getElementById('dVideo').style.display = 'inline';
  }
}
</script>
</head>
<body>

<a href="#" onClick="toggleDivFlagForm(); return false;">Toggle Form</a><br />

<div id="divFlagForm" style="position:absolute; left:100px; top:100px; display:none; ">
<form method="GET">
Name: <input type="text" name="name" /><br />
Email: <input type="text" name="email" /><br />
<input type="submit" value="Submit" />
</form>
</div>

<div id="dVideo">
<object style="visibility: visible;" id="flashcontent1273" data="http://fpdownload.adobe.com/strobe/FlashMediaPlayback.swf" type="application/x-shockwave-flash" height="390" width="584">
<param value="true" name="allowfullscreen">
<param value="always" name="allowscriptaccess">
<param value="src=http%3A%2F%2Fcache.nebula.phx3.secureserver.net%2Fobj%2FNDEyMkYyRDk1MEM3MENBN0FFRDM6YTE5MTgwMThlMGQ0OTEwY2RmOGUwZjMxZWM3NjA4ZTM%3D&amp;controlBarMode=docked&amp;controlBarAutoHide=false&amp;poster=http://www.koopman.me/wp-content/uploads/2011/01/OFF_Drop_VidScreen.jpg&amp;playButtonOverlay=true&amp;loop=false&amp;autoPlay=false&amp;streamType=liveOrRecorded&amp;scaleMode=letterbox" name="flashvars">
</object>
</div>

<script language="javascript">
if ((navigator.userAgent.indexOf('iPhone') != -1) || (navigator.userAgent.indexOf('iPod') != -1) || (navigator.userAgent.indexOf('iPad') != -1)) 
        document.getElementById("dVideo").innerHTML = '<video width="584" height="390" poster="http://www.koopman.me/wp-content/uploads/2011/01/OFF_Drop_VidScreen.jpg" src="http://cache.nebula.phx3.secureserver.net/obj/NDEyMkYyRDk1MEM3MENBN0FFRDM6YTE5MTgwMThlMGQ0OTEwY2RmOGUwZjMxZWM3NjA4ZTM" controls />'; 
</script>

</body>
</html>