Multi-Channel Audio
Delivering forty channel audio using QuickTime APIs to adjust movie files.
A little while ago, Oliver (Watershed's ICT Co-ordinator) , asked me to write a small command line tool to set the audio output channels of a QuickTime movie. Oliver was writing software for Dream Director, a project that plays audio to people sleeping in pods in response to rapid eye movement.
A Mac mini plays back the audio to up to twenty pods (containing sleeping people) through a collection of M-Audio Firewire410 boxes. As the audio-out hardware units have been aggregated into a single virtual device with forty available channels, it was just a case of playing back a stereo file through a selected pair of channels.
QuickTime movies will save the audio channel mapping inside the file, so the requirement was to build a tool that would set the selected channels in a movie and save the file to disk. The source listing is for a Cocoa command-line Tool, using QTKit, to open an audio file, set the track mapping and save as a QuickTime movie.
QuickTime now uses Core Audio to handle the audio channel mapping and I thought this may be of some use to people. The partial listing below shows the code needed to map audio channels using QuickTime and a link to the source file of the tool is below the listing. Sorry about the wrapped source listing.
Movie qtMovie = [movie quickTimeMovie];Track audioTrack = GetMovieIndTrack(qtMovie,1);AudioChannelLayout* trackChannelLayout = NULL;OSStatus err = noErr;UInt32 trackChannelLayoutSize;// Allocate a layout of the required sizetrackChannelLayoutSize = fieldOffset(AudioChannelLayout, mChannelDescriptions[2]);trackChannelLayout = (AudioChannelLayout*)calloc(1, trackChannelLayoutSize);trackChannelLayout->mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions;trackChannelLayout->mNumberChannelDescriptions = 2;// Adjust the channel Assignment so that for an index we get a pair of channel// allocations. The index starts at 1// index channelA channelB// -----------------------------// 1 discreet0 discreet1// 2 discreet2 discreet3// 3 discreet4 discreet5// 4 discreet6 discreet7// ... and so onchannelAssignment = (channelAssignment-1)*2;#warning This will break if Apple change the CoreAudio's Channel Layout internalstrackChannelLayout->mChannelDescriptions[0].mChannelLabel = (1L<<16) | channelAssignment;trackChannelLayout->mChannelDescriptions[1].mChannelLabel = (1L<<16) | (channelAssignment + 1);// Set the track layouterr = QTSetTrackProperty(audioTrack, kQTPropertyClass_Audio, kQTAudioPropertyID_ChannelLayout, trackChannelLayoutSize, trackChannelLayout);if (err != noErr) {NSLog(@"**Error** QuickTime SetPropertyError: %i", err);return 1;}
Download the full source code.
Where is the QuickTime I knew?
Interactive QuickTime is pretty much dead and the QuickTime (.mov) file format is dying.
A short while ago, whilst working on Electric December, I spent some more time working on server generated, interactive video presentation. This was an exact repeat of the previous year's Electric December development and once again I abandoned the work after a couple of weeks.
Yes, I know this type of thing can be done easily enough in Flash but I wanted to do it in QuickTime for a few reasons:
- We want to keep the video content in MPEG4 data files because we don't want to encode very large amounts of our content in a proprietry codec.
- In my opinion, the pereformance of MPEG4 is better than the Flash On2 codec.
- We need to distribute our content in a format that can be played on mobile devices such as iPods, PSPs and of course the iPhone.
In the Applesphere it appears that the QuickTime file format has been beaten down by MPEG4. The Apple TV doesn't appear to support QuickTime files and neither does the iPod. If the ipod doesn't support quicktime files then it is very unlikely the iPhone will. Interactivity and the other advanced features of MPEG4 are not supported in QuickTime and MPEG4 is seen as a linear audio and video format.
Interactivity in QuickTime has been neglected and become an embarrassment for Apple. QuickTime VR is hardly mentioned these days. Have you tried opening a .m4a file with chapter artwork and links in QuickTime Player? How ugly is the result? The chapter implementation in the QuickTime UI is neat and tidy but why draw text using Times, in 'link blue' across the artwork?
Apple recently disabled QuickTime's default ability to play Flash movies embedded inside a movie. Security issues with the existing code led Apple to turn this option off, without warning content producers this was going to happen. Flash playback in QuickTime couldn't have been a high priority. The user can re-activate the functionality, but the settings are hidden many levels down in nested preference panels, and not something you would expect an end user to perform in order to view content.
QuickTime's XML parsing and resource loading performance makes using techniques such as SMIL or wired, umbrella movies very difficult to deploy. How long can it take to display a few, small, simple media resources such as text and still images?
There are so many differences between the implementations of features, that haven't changed, in versions 6 and 7 of QuickTime? A content developer can't distinguish if something is working or not. Well, apart from text rendering which is not great in either. Why does QuickTime 7 install two different versions of the plug-in? One, a Coca/QTKit Webkit plug-in used by Safari, and the other, a Netscape style plug-in that all the other Macintosh browsers use. It would be quite nice if these two plug-ins displayed content and behaved identically. Based on content from Apple's own site, the Quicktime plug-in is used simply to provide basic, interactive playback of linear MPEG4 video controlled by Javascript. The interface is provided by the surrounding HTML.
It appears all the graphics & media engineers at Apple are working on technologies such as such as CoreAnimation, CoreVideo & Quartz Composer. All the advanced media technology work is done on the Mac OS X platform and not QuickTime! This is all great stuff and I love working in CoreVideo and CoreAnimation. They produce spectacular results and I amaze myself every time I click Build & Run. This is nothing we can deploy effectively to the public at large, for which the MS Windows using majority, the QuickTime plug-in is the only bridge there is. QuickTime will become a media generation framework to support Apple's pro & iLife applications, along with third party developer's desktop applications. The browser plug-in will just handle playback of MPEG4 data.
I guess what I'm trying to say is don't waste any more time trying to use QuickTime for interactive work, use it for what it's best at: playback of MPEG4 content and leave the interactivity & interface to Javascript & HTML.
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.
import quicktime.*;import quicktime.app.*;import quicktime.app.players.*;import quicktime.app.display.*;import quicktime.io.*;import quicktime.std.*;import quicktime.std.movies.*;import quicktime.qd.*;import quicktime.std.movies.media.*;public class GetImage {public GetImage() {}public void getImageFromMovie(String url, String offsetTime) {try {QTSession.open();DataRef ref = new DataRef(url);System.out.println("DataRef: " + ref);if (ref == null) return;Movie theMovie = Movie.fromDataRef(ref, 0);System.out.println(theMovie.getBounds());int theTime = Integer.parseInt(offsetTime) * theMovie.getTimeScale();System.out.println("theTime: " + theTime);Pict pictImage = theMovie.getPict(theTime);System.out.println("PICT: " + pictImage);// Optionally you could just use the poster image if it has been set by the person encoding the video//pictImage = theMovie.getPosterPict();// Now encode the Macintosh PICT as a JPEG or PNG or ....quicktime.std.image.GraphicsExporter graphicsExporter = new quicktime.std.image.GraphicsExporter(StdQTConstants.kQTFileTypeJPEG);graphicsExporter.setInputPicture(pictImage);QTFile exportFile = new QTFile("StillImage.jpg");graphicsExporter.setOutputFile(exportFile);System.out.println("graphicsExporter: " + graphicsExporter);// Do the exportint size = graphicsExporter.doExport();byte[] jpegBytes = graphicsExporter.GraphicsExportReadOutputData(0, size);System.out.println("jpegBytes: " + jpegBytes);QTSession.close();} catch (Exception e) {QTSession.close();System.out.println(e);System.exit(0);}}public static void main(String args[]) {if (args.length < 2) {System.out.println("You need to specify a URL and a location time in seconds when launching");return;}GetImage instance = new GetImage();instance.getImageFromMovie(args[0], args[1]);}}
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.