Programming blog by Ezekiel Victor

Get video and audio blob duration in HTML5

While using RecordRTC to record HTML5 webcam video/audio in the browser, I was miffed to find no duration or length property available upon deep introspection of the various types involved (MediaStream, MediaStreamTrack, RecordRTC itself, Blob, File).

It turns out that the streams themselves don’t have finite durations, which sort of makes sense if you consider that you could infinitely record if you wanted (though arguably a stream should have a finite duration when the stream is stopped or paused). Once you have captured a Blob from your video or audio stream, you do have something with a duration—but the Blob type itself is just a container for abstract data, so it does not expose any particular interface to obtain duration of video or audio.

The only way to get the video or audio recording’s duration is through HTML5 <video> or <audio> elements. If you don’t already have your stream attached to such an element, you can create one on-the-fly solely for the purpose of invisibly retrieving the Blob duration:

Along comes Chrome

Unfortunately, there is currently a Chromium bug that causes the duration not to be available under certain circumstances. In these conditions, you will see the video or audio duration as being Infinity (a vestige of the infinite stream concept, presumably).

Thankfully there is a fix in which you can set the element’s currentTime pointer long past the end of the clip, and the duration property will be updated appropriately. A pseudocode solution looks like this (thanks Kaiido):

A neatly packaged solution

So you don’t have to suffer a copy-pasta codebase, I produced a small npm package get-blob-duration that you can easily install, import, and use with a fluent, simple Promise interface:

Or for ECMAScript 6:

Enjoy.

read more

Beware of Lucene DAO when constructing queries

Jun 02, 15 Beware of Lucene DAO when constructing queries

When using Lucene in Java or Scala, you may be tempted to skip the QueryParser and use the “DAO” (for lack of a better term) to construct queries using the classes provided. It is generally a best practice to use DAOs and such abstractions when available over raw query compilation for a variety of reasons, foremost being security (implicit injection protection) and query syntax integrity.

However, you may experience perplexing, incorrect result sets with your Lucene query if the following circumstances are true:

  • Your index is written with an analyzer other than the default StandardAnalyzer (e.g. EnglishAnalyzer or any of the plethora of others).
  • Your query is a boolean query with number of OR (aka SHOULD) clauses where ≥ 2.
  • Your query requires a minimum m number of boolean clauses should match where m ≥ n.

Ordinary query, incorrect results

Here is a simple example of a query that exhibits the latter two circumstances above as built entirely with the DAO (code examples henceforth using Scala for brevity):

This query in plain English means “find documents that contain at least 2 of the terms thanksobama, and barack.”

Now imagine an index of documents as follows written with EnglishAnalyzer (or some other non-StandardAnalyzer):

Running the query on the above documents should yield 2 hits—documents #1 and #2. However, you will receive 0 results in Lucene 3.5.0 (and possibly other versions; did not check).

Unfortunately for me, I was stuck with Lucene 3.5.0 in this particular codebase. Luckily I found a way to sidestep the bug by avoiding the DAO for at least part of the query construction.

Same query, but without DAO (and working now!)

Surprise, surprise, this works! Documents #1 and #2 from before will match as expected.

Note on protecting against query injection

If you must use QueryParser.parse  as in the case above, you should also make it a habit to use  QueryParser.escape (a static method) on the string you pass to the parse method (e.g. myQueryParser.parse(QueryParser.escape("potentially dangerous user input")) ). The reasons are beyond the scope of this post; just Google “query injection” and pick one of the endless writings on that.

read more

Fixing autocomplete (autofill) on AngularJS form submit

Many browsers support autocomplete but do not trigger “change” events on inputs when the user initiates autocomplete. This is a problem for many libraries and code in the wild that rely on performing some action (e.g. input validation) when input data change.

With respect to AngularJS forms, the problem becomes obvious if you are using AngularJS form validation. If you autofill an empty form then press Submit, AngularJS will think the inputs are still empty:

AngularJS unaware of autofilled inputs

AngularJS unaware of autofilled inputs

Here is a simple login form subject to this issue:

Unfortunately the underlying issue of not having an appropriate event related to autofill must be addressed by browser vendors. However in the meantime, we can use a custom directive to ensure AngularJS knows about form changes made by autofill at time of form submit.

Patch directive

In CoffeeScript

In JavaScript

Directive in use

The directive is simple to use; just apply it to your form and away you go:

read more

How to use rich objects and typed objects with Bootstrap Typeahead

The JS components of Twitter Bootstrap are somewhat lacking in functionality when compared to well established plugins that do the same things (autocompletes, tooltips, etc.). However, I still use them on Bootstrap projects just because it is nice to have homogeneous interfaces to things—and, of course, it is easy then to jump on other Bootstrap projects and be in familiar territory right off the bat.

One of the continuing problems I face is with Bootstrap Typeahead, in particular its lack of native support for non-String items. I constantly come across this; rare is it that one can identify an item in a list by that item’s user-friendly string representation, i.e. more often than not you need to be working with a fully typed thing, not just a string.

Other autocompletes and typeaheads support rich objects out of the box but Typeahead needs a little massaging—fortunately not much, and not anything requiring changes to the core. Here is a sample showing a Typeahead that uses a rich UsState class (a natural extension to the Twitter demo using string state names):

Bootstrap Typeahead only gets tripped up with rich object sources for the updater method namely. The key component here is ensuring your class has a toString() method that serializes instances correctly, as well as a fromString() static method to deserialize. For my purposes I include the popular json2.js for JSON.stringify() and JSON.parse():

Then, in your Typeahead updater:

Note that Typeahead passes the stringified object, which we deserialize, and expects a string return to stuff into the text input.

And because I love CoffeeScript so much, here is the same demo in CS:

read more

PHP error_reporting E_STRICT at runtime

Often times PHP applications configure error_reporting at runtime, perhaps because it appears to be more bootstrappable:

In dev environments, it is often desirable to log errors of level E_STRICT to be warned about practices that are “deprecated or not future proof.” Unfortunately, enabling E_STRICT at runtime using one of the methods above will never work—giving you a false sense of security with respect to strict-level errors! This is because PHP performs strict checks at compile time before your runtime error_reporting configs are set. In other words, this will not work:

To get E_STRICT errors, you must take care to set the value of error_reporting before compile time, such as in php.ini, or httpd.conf or .htaccess if you are running Apache:

Setting error_reporting in php.ini:

Setting error_reporting in httpd.conf or .htaccess:

The manual does mention this topic, though it may be easily overlooked.

Last but not least, always remember to turn display_errors off in production!

display_errors Off in php.ini

display_errors Off in httpd.conf or .htaccess

read more