34.1 Automating Repetitive Tasks

Splitting a movie

The automation of repetitive, well-defined tasks can be accomplished with simple programming language constructs. A video editor may want to divide a long video sequence into smaller, equal-sized chunks. By hand this would be a tedious, error-prone process, but in VideoScheme it can be performed with a simple program:

(define split-movie
 (lambda (movie chunk-size)
 	(let
	    ((time 0.0))
	(while (< time (get-movie-duration movie))

    	    ;copy the next chunk of the movie
	    (copy-movie-clip movie time chunk-size)

    	    ;paste it into a new movie
	    (paste-movie-clip (new-movie) 0.0 0.0)

	(set! time (+ time chunk-size))))))

With the function thus defined, splitting the frontmost movie into one-minute-sections is as simple as evaluating the expression (split-movie (get-front-movie) 60).

Speeding up a movie

Similarly, a single new movie can be created by choosing multiple excerpts from an existing movie. Indeed, by this simple formula we can achieve the effect of speeding up the movie:

(define speedup
 (lambda (movie factor)
	(let
	    ((time 0.0)
	    (new (new-movie)))
	(while (< time (get-movie-duration movie))
	
	    ;copy a fraction of the next tenth of a second
	    (copy-movie-clip movie time (/ 0.1 factor))

	    ;paste it at the end of the new movie
	    (paste-movie-clip new
	       (get-movie-duration new)
	       (get-movie-duration new))

	(set! time (+ time 0.1)))
	new)))

So the expression (speedup (get-front-movie) 2) returns a version of the frontmost movie that appears to run at double speed, since every-other twentieth of a second has been removed from it. An analogous function could be written to duplicate information in a movie rather than removing it, yielding a slow-motion effect.

Reversing a movie

We can make these mechanical functions sensitive to the structure of the movie with the aid of VideoScheme's built-in functions. One of these, get-next-frame-time, returns a list consisting of the timestamp and duration of the next frame in a video track. With this function we can copy a movie on a frame by frame basis, reconstructing it in reverse order:

(define reverse
 (lambda (movie trackno)
	(let
	   ((time 0.0)
	    (frame-info nil)
	    (duration 0.0)
	    (new (new-movie)))
	(while (< time (get-movie-duration movie))

	    ;find out when the next frame starts,
	    ;and how long it lasts
	    (set! frame-info
	     (get-next-frame-time movie trackno time))
	    (set! time (car frame-info))
	    (set! duration (car (cdr frame-info)))

	    ;copy the next frame
	    (copy-movie-clip movie time duration)

	    ;paste it at the beginning of the new movie
	    (paste-movie-clip new 0.0 0.0)

	    (set! time (+ time duration)))
	new)))

Simple, repetitive functions are called for in some circumstances, but their power is clearly limited by their simplicity. Most video editing decisions must take the content of the video data into account, and likewise more powerful VideoScheme functions can be created when the media itself is consulted. VideoScheme includes two built-in functions for accessing the movie data: get-audio-samples and get-video-frame. Each of these returns arrays of integers: 8-bit sound samples in the case of get-audio-samples, and 24-bit color pixel values in the case of get-video-frame. These arrays can then be analyzed and the results used to create new editing functions.

Searching for silence

One straight-forward application is to search through video data for periods of silence. We can characterize silence as a period where none of the audio samples has an amplitude greater than 10 (out of a maximum amplitude of 128). The returned samples are in the range of 0-255, where the sample value 128 has an amplitude of zero. Therefore our silence predicate looks like the following:

(define silence?
 (lambda (movie trackno time interval)
	(let
	   ((samples (cons-array 0 'long)))

	   ; get an array of audio samples
	   (get-audio-samples movie trackno time
	    interval samples)

	   ; compute their absolute amplitudes
	   (adiff samples 128 samples)
	   (aabs samples samples)

	   ; is the loudest sample less than 10?
	   (< (amax samples) 10))))

This predicate may prove unreliable with noisy audio sources; in that case examining the median amplitude, or a certain percentile might prove more effective. These possibilities can be easily explored with VideoScheme.