This is a really cool widget that Scott built at an event we attended over the last couple of days. I wanted to see it go straight into the main trunk, but he wanted to leave it in scratchpad until fully tested.
So, can people please test this widget - it enables you to add captions to a video that plays in the widget itself, great stuff. A widget with a real use case and thus more likely to attract enhancements. Ross On 22 June 2011 14:36, <[email protected]> wrote: > Author: scottbw > Date: Wed Jun 22 13:36:21 2011 > New Revision: 1138459 > > URL: http://svn.apache.org/viewvc?rev=1138459&view=rev > Log: > Committed first version of VTT closed-captioning HTML5 widget > > Added: > incubator/wookie/trunk/scratchpad/widgets/vtt/ > incubator/wookie/trunk/scratchpad/widgets/vtt/build.xml > incubator/wookie/trunk/scratchpad/widgets/vtt/config.xml > incubator/wookie/trunk/scratchpad/widgets/vtt/icon.png (with props) > incubator/wookie/trunk/scratchpad/widgets/vtt/index.html > incubator/wookie/trunk/scratchpad/widgets/vtt/scripts/ > incubator/wookie/trunk/scratchpad/widgets/vtt/scripts/controller.js > > Added: incubator/wookie/trunk/scratchpad/widgets/vtt/build.xml > URL: > http://svn.apache.org/viewvc/incubator/wookie/trunk/scratchpad/widgets/vtt/build.xml?rev=1138459&view=auto > ============================================================================== > --- incubator/wookie/trunk/scratchpad/widgets/vtt/build.xml (added) > +++ incubator/wookie/trunk/scratchpad/widgets/vtt/build.xml Wed Jun 22 > 13:36:21 2011 > @@ -0,0 +1,23 @@ > +<?xml version="1.0"?> > +<!-- > + Licensed to the Apache Software Foundation (ASF) under one or more > + contributor license agreements. See the NOTICE file distributed with > + this work for additional information regarding copyright ownership. > + The ASF licenses this file to You under the Apache License, Version 2.0 > + (the "License"); you may not use this file except in compliance with > + the License. You may obtain a copy of the License at > + > + http://www.apache.org/licenses/LICENSE-2.0 > + > + Unless required by applicable law or agreed to in writing, software > + distributed under the License is distributed on an "AS IS" BASIS, > + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. > + See the License for the specific language governing permissions and > + limitations under the License. > +--> > +<project default="build-widget" basedir="." name="widget build file"> > + <property name="wookie.widgets.dir" location="../"/> > + <property name="widget.shortname" value="vtt"/> > + > + <import file="../build.xml"/> > +</project> > \ No newline at end of file > > Added: incubator/wookie/trunk/scratchpad/widgets/vtt/config.xml > URL: > http://svn.apache.org/viewvc/incubator/wookie/trunk/scratchpad/widgets/vtt/config.xml?rev=1138459&view=auto > ============================================================================== > --- incubator/wookie/trunk/scratchpad/widgets/vtt/config.xml (added) > +++ incubator/wookie/trunk/scratchpad/widgets/vtt/config.xml Wed Jun 22 > 13:36:21 2011 > @@ -0,0 +1,46 @@ > +<!-- > + Licensed to the Apache Software Foundation (ASF) under one or more > + contributor license agreements. See the NOTICE file distributed with > + this work for additional information regarding copyright ownership. > + The ASF licenses this file to You under the Apache License, Version 2.0 > + (the "License"); you may not use this file except in compliance with > + the License. You may obtain a copy of the License at > + > + http://www.apache.org/licenses/LICENSE-2.0 > + > + Unless required by applicable law or agreed to in writing, software > + distributed under the License is distributed on an "AS IS" BASIS, > + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. > + See the License for the specific language governing permissions and > + limitations under the License. > +--> > +<widget xmlns="http://www.w3.org/ns/widgets" > + id="http://wookie.apache.org/widgets/vtt" > + version="0.1" > + width="520" > + height="480" > + > > + <name>VTT</name> > + <description>A Widget for creating web-VTT caption files</description> > + <author>Apache Wookie (Incubating) Team</author> > + <feature name="http://jquerymobile.com" required="true"/> > + > + <licence>Licensed to the Apache Software Foundation (ASF) under one or more > + contributor license agreements. See the NOTICE file distributed with > + this work for additional information regarding copyright ownership. > + The ASF licenses this file to You under the Apache License, Version 2.0 > + (the "License"); you may not use this file except in compliance with > + the License. You may obtain a copy of the License at > + > + http://www.apache.org/licenses/LICENSE-2.0 > + > + Unless required by applicable law or agreed to in writing, software > + distributed under the License is distributed on an "AS IS" BASIS, > + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. > + See the License for the specific language governing permissions and > + limitations under the License.</licence> > + > +</widget> > + > + > + > > Added: incubator/wookie/trunk/scratchpad/widgets/vtt/icon.png > URL: > http://svn.apache.org/viewvc/incubator/wookie/trunk/scratchpad/widgets/vtt/icon.png?rev=1138459&view=auto > ============================================================================== > Binary file - no diff available. > > Propchange: incubator/wookie/trunk/scratchpad/widgets/vtt/icon.png > ------------------------------------------------------------------------------ > svn:mime-type = application/octet-stream > > Added: incubator/wookie/trunk/scratchpad/widgets/vtt/index.html > URL: > http://svn.apache.org/viewvc/incubator/wookie/trunk/scratchpad/widgets/vtt/index.html?rev=1138459&view=auto > ============================================================================== > --- incubator/wookie/trunk/scratchpad/widgets/vtt/index.html (added) > +++ incubator/wookie/trunk/scratchpad/widgets/vtt/index.html Wed Jun 22 > 13:36:21 2011 > @@ -0,0 +1,141 @@ > +<!-- > + Licensed to the Apache Software Foundation (ASF) under one or more > + contributor license agreements. See the NOTICE file distributed with > + this work for additional information regarding copyright ownership. > + The ASF licenses this file to You under the Apache License, Version 2.0 > + (the "License"); you may not use this file except in compliance with > + the License. You may obtain a copy of the License at > + > + http://www.apache.org/licenses/LICENSE-2.0 > + > + Unless required by applicable law or agreed to in writing, software > + distributed under the License is distributed on an "AS IS" BASIS, > + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. > + See the License for the specific language governing permissions and > + limitations under the License. > +--> > +<!DOCTYPE html> > +<html> > + <head> > + <meta http-equiv="pragma" content="no-cache"/> > + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> > + <script type="text/javascript" src="scripts/controller.js" > charset="utf-8"></script> > + > + <!-- > + > + // Removed for now - we may be able to use Playr to do previewing, > but it isn't > + // necessary for creating the web-vtt file > + // See http://www.delphiki.com/html5/playr/ > + > + <script type="text/javascript" src="lib/playr.js" > charset="utf-8"></script> > + <link rel="stylesheet" href="lib/playr.css"/> > + > + --> > + > + <!-- > + > + // If you aren't using this in Apache Wookie, uncommment this section > + > + <script type="text/javascript" src="lib/jquery-1.5.min.js"></script> > + <script type="text/javascript" > src="lib/jquery.mobile-1.0a4-patched.min.js"></script> > + <link type="text/css" rel="stylesheet" > href="lib/jquery.mobile-1.0a4.min.css" /> > + > + --> > + > + <title>VTT</title> > + </head> > + > + <body onLoad="Controller.init()"> > + <div data-role="page" id="home"> > + > + <div data-role="header"> > + <h4>VTT Caption Creator</h4> > + <a href="#add" data-rel="dialog" > data-transition="pop" data-role="button" data-icon="plus">Video</a> > + <a href="#output" data-rel="dialog" data-transition="pop" > data-role="button" data-icon="grid">VTT</a> > + </div> <!-- /header --> > + > + <div data-role="content" class="ui-content"> > + <div id="video_container"> > + <!-- video is placed here --> > + <div id="no-video"> > + <p> > + Welcome to the VTT subtitle track creator. Click > the "Video" button to select a video to subtitle. > + </p> > + </div> > + </div> > + > + <div> > + <!-- these are the caption creation tools --> > + <div id="captionTrigger"> > + <button id="startButton" > onclick="Controller.startCaption()">Pause and create caption</button> > + </div> > + <div id="captionTools"> > + <div data-role="controlgroup" data-type="horizontal"> > + <input id="captionText"/> > + <button id="okButton" > onclick="Controller.endCaption()">OK</button> > + <button id="cancelButton" > onclick="Controller.cancelCaption()">Cancel</button> > + </div> > + </div> > + </div> > + </div><!-- /content --> > + > + </div><!-- /page --> > + > + <!-- > + This is the dialog box that shows the Web-VTT output you've created. > + ---> > + <div data-role="dialog" id="output"> > + <div data-role="header"> > + <h4>VTT Output</h4> > + </div> <!-- /header --> > + <div data-role="content" class="ui-content"> > + <div> > + <textarea style="width:100%; height:250px; font-family: > courier" id="vtt_out"></textarea> > + <a href="#preview" data-transition="pop" > data-role="button" onclick="Controller.preview()">Preview</a> > + <a href="#home" data-transition="pop" > data-direction="reverse" data-role="button">OK</a> > + </div> > + </div><!-- /content --> > + </div><!-- /page --> > + > + > + <!-- > + This is the dialog box that lets you set the video to show and work > on. > + ---> > + <div data-role="dialog" id="add"> > + <div data-role="header"> > + <h4>Select Video to Use</h4> > + </div> <!-- /header --> > + <div data-role="content" class="ui-content"> > + <div data-role="fieldcontain"> > + <label for="input-url-mp4">MP4 URL:</label> > + <input type="text" name="input-url-mp4" > id="input-url-mp4" value="" /> > + <label for="input-url-ogg">Ogg URL:</label> > + <input type="text" name="input-url-ogg" > id="input-url-ogg" value="" /> > + </div> > + <button id="submit-button" > onclick="Controller.setVideo()">OK</button> > + <a href="#home" data-transition="pop" > data-direction="reverse" data-role="button">Cancel</a> > + </div><!-- /content --> > + </div><!-- /page --> > + > + <!-- > + This is the dialog box that shows a preview of the video with the > subtitle track > + ---> > + <div data-role="page" id="preview"> > + <div data-role="header"> > + <h4>VTT Preview</h4> > + </div> <!-- /header --> > + <div data-role="content" class="ui-content"> > + <div> > + <p>Unfortunately, Preview doesn't work at the moment - > please fix!</p> > + <div id="video_preview_container"> > + <!-- video is placed here --> > + </div> > + <a href="#home" data-transition="pop" > data-direction="reverse" data-role="button">OK</a> > + </div> > + </div><!-- /content --> > + </div><!-- /page --> > + > + > + > + </body> > +</html> > \ No newline at end of file > > Added: incubator/wookie/trunk/scratchpad/widgets/vtt/scripts/controller.js > URL: > http://svn.apache.org/viewvc/incubator/wookie/trunk/scratchpad/widgets/vtt/scripts/controller.js?rev=1138459&view=auto > ============================================================================== > --- incubator/wookie/trunk/scratchpad/widgets/vtt/scripts/controller.js > (added) > +++ incubator/wookie/trunk/scratchpad/widgets/vtt/scripts/controller.js Wed > Jun 22 13:36:21 2011 > @@ -0,0 +1,228 @@ > +/* > + * Licensed to the Apache Software Foundation (ASF) under one or more > + * contributor license agreements. See the NOTICE file distributed with > + * this work for additional information regarding copyright ownership. > + * The ASF licenses this file to You under the Apache License, Version 2.0 > + * (the "License"); you may not use this file except in compliance with > + * the License. You may obtain a copy of the License at > + * > + * http://www.apache.org/licenses/LICENSE-2.0 > + * > + * Unless required by applicable law or agreed to in writing, software > + * distributed under the License is distributed on an "AS IS" BASIS, > + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. > + * See the License for the specific language governing permissions and > + * limitations under the License. > + */ > + > + > +/** > + * TODO LIST > + * > + * Fix video-with-captions preview > + * Clear input after user puts in a subtitle > + * Add keyboard input controls > + * Cool styling of captions > + * Dynamic length setting > + */ > + > +/** > + * The Controller object > + * This is used to wire up the view and model with actions > + */ > +var Controller = { > + > + // Setup the controller > + init:function() { > + // Set some defaults up in the "video" dialog > + > $("#input-url-mp4").attr("value","http://www.delphiki.com/html5/playr/examples/dw_trailer_low.mp4"); > + > $("#input-url-ogg").attr("value","http://www.delphiki.com/html5/playr/examples/dw_trailer_low.ogg"); > + > + // Create new caption set > + this.captions = []; > + // Hide the caption editing tools until we have a video > + $("#captionTrigger").hide(); > + $("#captionTools").hide(); > + }, > + > + select: function(){ > + }, > + > + // Called when the user wants to pause the video > + // and write a caption. Enables the caption editing controls. > + startCaption: function(){ > + this.video.pause(); > + this.now = this.video.currentTime; > + $("#captionTrigger").hide(); > + $("#captionTools").show(); > + }, > + > + // Called when the user has finished writing a caption > + // Saves the caption and resumes the video > + endCaption: function(){ > + var caption = {}; > + caption.text = document.getElementById('captionText').value; > + // We start the captioning 250 milliseconds before the current frame > + caption.start = this.formatDate(this.now * 1000 - 250); > + // We end the caption 2 seconds after the caption start > + caption.end = this.formatDate((this.now + 2) * 1000); > + this.captions.push(caption); > + this.updateCaptions(); > + $("#captionTrigger").show(); > + $("#captionTools").hide(); > + this.video.play(); > + }, > + > + // Called if the user cancels writing a caption > + cancelCaption: function(){ > + $("#captionTrigger").show(); > + $("#captionTools").hide(); > + > + this.video.play(); > + }, > + > + // Update the Web-VTT serialization of the captions > + updateCaptions: function(){ > + var vtt = "WEBVTT FILE"; > + for(i=0;i<this.captions.length;i++){ > + vtt += "\n"; > + var x = i + 1; > + vtt += "\n" + x; > + vtt += "\n" + this.captions[i].start +" --> " + > this.captions[i].end; > + vtt += "\n" +this.captions[i].text; > + } > + document.getElementById('vtt_out').innerHTML = vtt; > + }, > + > + // Turns a JS date into a Web-VTT timestamp > + formatDate: function(inputDate){ > + var date = new Date(inputDate); > + var timestamp; > + if (date.getHours() < 10){ > + timestamp = "0"+date.getHours(); > + } else { > + timestamp = date.getHours(); > + } > + timestamp +=":"; > + if (date.getMinutes() < 10){ > + timestamp += "0"+date.getMinutes(); > + } else { > + timestamp += date.getMinutes(); > + } > + timestamp +=":"; > + if (date.getSeconds() < 10){ > + timestamp += "0"+date.getSeconds(); > + } else { > + timestamp += date.getSeconds(); > + } > + timestamp += "."; > + if (date.getMilliseconds() < 100){ > + timestamp += "0"; > + } > + timestamp += date.getMilliseconds(); > + return timestamp; > + }, > + > + // Called when OK is clicked in the add video dialog > + setVideo: function(){ > + // Get the form values > + var video_src_mp4 = $("#input-url-mp4").attr("value"); > + var video_src_ogg = $("#input-url-ogg").attr("value"); > + > + // Set the video if there is at least one src value > + if (video_src_mp4 != "" || video_src_ogg != ""){ > + this.resetVideo(video_src_mp4,video_src_ogg, null); > + > + // Make the caption trigger visible only if there is a valid > video > + $("#captionTrigger").show(); > + } > + > + // Close the dialog > + $.mobile.changePage("#home", "pop", true); > + }, > + > + // Reset the preview dialog > + preview: function(){ > + > + // Create video tag > + var video_src_mp4 = $("#input-url-mp4").attr("value"); > + var video_src_ogg = $("#input-url-ogg").attr("value"); > + var track_src = "data:text/plain,"+"\n"+$("#vtt_out").val(); > + var video = this.createVideoTag(video_src_mp4, video_src_ogg, > track_src); > + > + // Remove any existing preview > + $('#video_preview_container').empty(); > + > + // Set video tag in the preview container > + $('#video_preview_container').append(video); > + > + // Update video tags using Playr > + this.updateVideoTags(); > + }, > + > + // Reset the video selection > + resetVideo: function(video_src_mp4, video_src_ogg, track_src){ > + > + // Remove placeholder > + $("#no-video").remove(); > + > + // Remove old video > + $("#video_container").empty(); > + > + // Create video tag > + var video = this.createVideoTag(video_src_mp4, video_src_ogg, > track_src); > + > + // Set video tag in the container > + $('#video_container').append(video); > + > + this.video = document.getElementsByTagName('video')[0]; > + > + // Update video tags using Playr > + // this.updateVideoTags(); > + > + }, > + > + // Create a video tag > + createVideoTag: function(video_src_mp4, video_src_ogg, track_src){ > + > + // Create video tag > + var video = $(document.createElement('video')) > + .attr('id', 'video') > + .attr('controls', 'controls') > + .attr('class','playr_video'); > + > + // Create source tags > + var mp4source = $(document.createElement('source')) > + .attr('type','video/mp4') > + .attr('src', video_src_mp4); > + video.append(mp4source); > + var oggsource = $(document.createElement('source')) > + .attr('type','video/ogg') > + .attr('src', video_src_ogg); > + video.append(oggsource); > + > + // Create subtitle tag > + if (track_src){ > + var track = $(document.createElement('track')) > + .attr('kind', 'subtitles') > + .attr('label', 'WebVTT') > + .attr('src', track_src) > + .attr('srclang', 'en') > + video.append(track); > + } > + > + return video; > + }, > + > + // NOTE I've removed this capability as its not clear what the license > + // is for Playr. > + // > + // Tell Playr to update all video tags in the app > + updateVideoTags: function(){ > + var video_tags = document.querySelectorAll('video.playr_video'); > + var video_objects = []; > + for(v = 0; v < video_tags.length; v++){ > + video_objects.push(new Playr(v, video_tags[v])); > + } > + } > +} > \ No newline at end of file > > > -- Ross Gardler <[email protected]> Programme Leader (Open Development) OpenDirective http://opendirective.com
