May 2006

Server Side Stills from QuickTime

Generating still JPEG images from QuickTime movies using Java running on the server.

Often it is useful to generate preview thumbnail images of QuickTime video movies on the server. CMS type applications that allow an admin user to upload and display video would be the most obvious use of this.

Having said that, generating still images on the desktop is far quicker and more efficient. Opening 80MB video files, over the network, in the web application's RAM in not the best use of resources. This solution requires Java 1.4.1 to be running on the server and most importantly requires QuickTime for Java. QuickTime for Java is essentially a series of JNDI hooks into the native C libraries of QuickTime. What this means is that this can only be deployed on MacOS X or MS Windows servers.

Watershed uses something like the code below in WebObjects applications as part of the QuickTime generation and manipulation classes used in web sites such as watershed.co.uk, electricdecember.org and dshed.net. These are expensive operations and the results should be aggressively cached either in RAM or on disk.

The code below has been a bit mangled to fit the narrow columns and still has a lot of commented-out logging statements.

  1. import quicktime.*;
  2. import quicktime.app.*;
  3. import quicktime.app.players.*;
  4. import quicktime.app.display.*;
  5. import quicktime.io.*;
  6. import quicktime.std.*;
  7. import quicktime.std.movies.*;
  8. import quicktime.qd.*;
  9. import quicktime.std.movies.media.*;
  10. public class GetImage {
  11. public GetImage() {
  12. }
  13. public void getImageFromMovie(String url, String offsetTime) {
  14. try {
  15. QTSession.open();
  16. DataRef ref = new DataRef(url);
  17. System.out.println("DataRef: " + ref);
  18. if (ref == null) return;
  19. Movie theMovie = Movie.fromDataRef(ref, 0);
  20. System.out.println(theMovie.getBounds());
  21. int theTime = Integer.parseInt(offsetTime) * theMovie.getTimeScale();
  22. System.out.println("theTime: " + theTime);
  23. Pict pictImage = theMovie.getPict(theTime);
  24. System.out.println("PICT: " + pictImage);
  25. // Optionally you could just use the poster image if it has been set by the person encoding the video
  26. //pictImage = theMovie.getPosterPict();
  27. // Now encode the Macintosh PICT as a JPEG or PNG or ....
  28. quicktime.std.image.GraphicsExporter graphicsExporter = new quicktime.std.image.GraphicsExporter(StdQTConstants.kQTFileTypeJPEG);
  29. graphicsExporter.setInputPicture(pictImage);
  30. QTFile exportFile = new QTFile("StillImage.jpg");
  31. graphicsExporter.setOutputFile(exportFile);
  32. System.out.println("graphicsExporter: " + graphicsExporter);
  33. // Do the export
  34. int size = graphicsExporter.doExport();
  35. byte[] jpegBytes = graphicsExporter.GraphicsExportReadOutputData(0, size);
  36. System.out.println("jpegBytes: " + jpegBytes);
  37. QTSession.close();
  38. } catch (Exception e) {
  39. QTSession.close();
  40. System.out.println(e);
  41. System.exit(0);
  42. }
  43. }
  44. public static void main(String args[]) {
  45. if (args.length < 2) {
  46. System.out.println("You need to specify a URL and a location time in seconds when launching");
  47. return;
  48. }
  49. GetImage instance = new GetImage();
  50. instance.getImageFromMovie(args[0], args[1]);
  51. }
  52. }

Using the code

The following instructions assume you are using a Macintosh but are almost identical for other platforms. First, ensure that you have QuickTime for Java installed. Copy the code above into a text file and save the file as GetImage.java on the Desktop, or alternatively download the class in a .java file. Next, assuming you have a JDK installed, compile the source. Installing Apple's Xcode Tools will give you a Java compiler. Open the Terminal application and compile by typing:

javac -classpath /System/Library/Java/Extensions/QTJava.zip GetImage.java

A file named GetImage.class will be produced. Alternatively download the compiled application. To run the application, navigate to the directory containing the GetImage.class and type something like:

java -classpath /System/Library/Java/Extensions/QTJava.zip: GetImage http://localhost/Cremaster.mov 22

The application will save the result as a file named StillImage.jpg in the same directory. The image produced is not scaled but this is fairly easy to add in. The code sample above contains lots of debug logging so remove the System.out.println lines.

|

MPEG4 on dShed

For the last eight years Watershed has always distributed video over the Web using QuickTime .mov files. The last time we explored encoding and distribution standards was during the research stage of the Digitised project in 2001. As we start to think about dShed and the implications of a digital archive it's time to look at how we produce, and our users consume, video.

As all of the video content becomes part of the dShed archive we need to think about what is best for the future users of the archive not just the users of dShed this week.

The move away from Sorenson Video codec in QuickTime could be a painful process. Using MPEG4 pt10 files in Electric December 2005 meant that almost all of Watershed's staff were unable to view the video content. The public viewing computers around the building all required upgrades.

Apple have set the hardware and OS bar quite high for QuickTime 7, especially (and ironically) for Macintosh users. Many Windows users are reticent about upgrading to QuickTime 7 because the most prominently displayed installer installs iTunes as an 'added extra'. iTunes will probably become Apple's default media player in the future replicating the UI mistakes Real made almost 10 years ago.

The transition to MPEG4 will be a gradual process. Currently some QuickTime files use h264 and AAC encoding. Even when the files become fully compliant we will still push the files through the QuickTime plug-in to maintain a consistently good user experience (unless they don't have QuickTime installed).

Using h264 and AAC gives much smaller file sizes for the equivalent quality. This saving can be substantial with thousands of visitors viewing large video files. We get reduced bandwidth costs and the users spend less time downloading and more time viewing. Other advantages include local colour and gamma correction. Some people compress a different version with colour and gamma settings for each platform; we didn't. Previously, the gamma was set somewhere between that of a Macintosh and a Windows PC, with no user getting the best experience.

We may lose some content viewers by requiring QuickTime 7 to view the video in the browser but we will gain many more users by leveraging a common, standard media format that is supported by low power consumption, hardware decoders in a variety of portable devices. The iPod and PSP currently account for most of these, but their share will diminish as more and more mobile phones get the decoders.
New distribution methods, such as video podcasts, allow us to broadcast further to an audience that has 'opted in' to view specific content. After we added a 90 Second Challenge video podcast to the iTunes Music Store, even before video iPods were released, the feed accounted for 62% of all traffic to dShed.
In the short-term we may loose up to 30% of current potential viewers but will gain more than a 300% increase through new deployment opportunities.

The podcast distribution format appears almost too good to be true. It took half a day to add the podcast to the web application. The podcast is marketed by Apple (using iTMS) and other directory sites to a very large number of users at no cost or effort on our part. It is quite wondrous when comparing the time and money spent developing large content umbrella and directory sites. There may even be a situation where we don't need a web-site - just a podcast.

|

odds&ends…
Benjamin Miller