Posts tagged video

Canon Vixia HV40 HDV Format Notes

So far I have always converted my HDV footage to NTSC before editing. For a small project I’m working on now, I’ve decided to try working directly with the raw HDV footage.

This thread explains why my m2t files show up as 1440×1080 even though they can be edited as 1920×1080 (aka 1080i). It has to do with square vs. rectangular pixels — or something — it doesn’t really matter. More general info on formats is here.

In Cinelerra, you must set the project format to 1440×1080, 16:9 ratio, then make sure you select “match output size” by right-clicking on the video track(s). This looks okay in the compositor window in Cinelerra, but the resulting file plays by default at 4:3 aspect ratio. You can set this manually when you open the video in VLC and see that everything looks okay. The only method I have found so far for getting the rendered video to play as 16:9 by default is by using a command such as this on to re-encode it after the fact:

ffmpeg -i full_render_test.mov -aspect 16:9 -sameq full_render_test_16-9.mov

For rendering in various formats, follow the instructions here as usual.

Web Video

I’ve been experimenting with video codecs and formats for uploading video to the web (Facebook, Youtube, etc.).

Encoding for the Web

To make a tiny file, you can encode files this way:

ffmpeg -i foo.dv foo.mp4

For better quality output, there are a number of variables you can control. I’m starting with two assumptions for the time being: I’m using the h264 codec and my target output format is mp4. For YouTube, flv would be better.

ffmpeg -i foo.dv -ab 128k -ar 44100 -b 1200k -vc h264 -qscale 1 -s 480×360 foo.mp4

“-i foo.dv” just identifies the input file, and the rest of the options apply to the output file.

For my own future benefit, I will break down the options I’ve used: “-ab 128k” is the audio bitrate, “-ar 44100″ is the audio sampling frequency (44100 is the default anyhow); “-b 1200k” is the video bitrate; “-vc h264″ is the video codec; “-qscale 1″ sets the video quantizer scale (lower is better quality, use “-sameq” for the same quality); “-s 480×360″ is the target width and height. All of these variables can be changed to create a higher/lower quality file which is smaller/larger in size. These settings create a decent output file for people to download, but it will be resampled on uploading to websites for streaming.

FFMPEG Tricks

If you just want to do a quick trim of the clip before uploading, I’ve found this is an easy way to do it. First play the video:

mplayer -osdlevel 3 -menu -loop 0 -dr -ni -framedrop -autosync 30 -msglevel all=0 -really-quiet -nolirc foo.dv

Note the start and end points you want, then run the ffmpeg command with “-ss NN” for the starting point in seconds and “-t NN” for the duration. That allows you to trim either the start or end of the clip without having to break out Cinelerra or Kino. By the way, I’ve got a pile of switches enabled on mplayer, but the only one that really matters is “-osdlevel 3″ so you can see the counter.

Some Youtube guidance on formats here: http://www.google.com/support/youtube/bin/answer.py?answer=132460&safe=off

Facebook format details are found here. You could use this command and vary the qscale and bitrate to get a reasonable file size:

ffmpeg -i foo.dv -acodec libfaac -ab 128k -b 1200k -vc h264 -qscale 6 foo.mp4

Vimeo format recommendations give specific values for bit rates and codecs as follows for high quality:

ffmpeg -i foo.dv -acodec libfaac -ab 320k -b 2000k -vc h264 -sameq foo.mp4

For HD video on Vimeo:

ffmpeg -i foo.m2t -acodec libfaac -ab 320k -b 3000k -vc h264 -sameq -s hd720 foo.mp4

“-s hd720″ tells ffmpeg to create 1280×720 output.

Sources of Information

This video is a good ffmpeg intro: http://www.linuxjournal.com/video/linux-howto-video-editing-magic-ffmpeg

For Youtube uploads, they use the following command. The presenter explains that these parameters are good for Youtube because they will not be re-encoded on upload:

ffmpeg -i foo.mov -ar 22050 -acodec libmp3lame -ab 32k -r 25 -s 320×240 -vcodec flv -qscale 9.5 foo.flv

He also shows how to crop and letterbox using ffmpeg and even creates a moving spotlight. He also uses the “-loop_input” ffmpeg switch in order to make a 10 second clip of a still frame. Very handy!

ffmpeg -loop_input -i still.png -t 10 -r 29.97 -qscale 2 extendedstill.mpg

Here is an explanation of how to use ffmpeg for screencasting.

Extract Audio Track from a Video File

I needed to isolate the audio track from an HDV video I captured from my camera. This command worked great:

mplayer -dumpaudio video.m2t -dumpfile audio.mp3

as discussed here: http://linux.byexamples.com/archives/229/extract-audio-from-video-or-online-stream/

UPDATE: To extract wav audio data from a dv file, I had to use this command:

ffmpeg -i video.dv -vn -acodec copy audio.wav

Details here: http://www.tuxradar.com/content/ffmpeg-made-easy

Video Production on Linux Workshop

I’m putting on a workshop/demo this evening to introduce some people to open source software and Linux for video editing. Here are the handouts: linux_video.

Thanks to Western Arctic Moving Pictures for hosting the workshop!

Scripts for Monkeying with Cinelerra XML

I’ve moved my Cinelerra projects from one directory path to another and scrambled a few things in the process. I’ve written a few bash scripts which helped me sort things out.

In the process, I’ve learned a bit about the xml format which Cinelerra uses to store references to files and edits. When you add a resource, it appears twice between opening and closing “ASSET” tags with the format <ASSET SRC=”/path/to/filename”>[asset details]</ASSET>. Then every time you include that file in a track of your project, the filename appears again in an “EDIT” tag complex in the format <FILE SRC=”/path/to/filename”>[edit details]</FILE>

First, I needed to check the paths for all the resources in the file to make sure they are still valid. I called this program test_xml_paths.sh. I corrected the incorrect paths with a text editor, but found that Cinelerra was still crashing with a memory error when I loaded the project.

Second, I decided to find and eliminate all of the unused assets in the file. I originally had a forty minute video in one file, but some time ago I split the project into four ten minute chunks. When I created the original project, I had added a couple of thousands of clips for possible inclusion, so now that I’m working on the final cut, I don’t need all that bloat.

I created a function to figure out which assets were being used in the edit list and which were not: list_unused_assets.sh.

Finally, I wrote a script which would recreate a new xml project file with all the redundant assets removed: remove_unused_assets.sh.

I can’t offer any warranty on these scripts, of course, but I hope they may help somebody else. If nothing else, there’s a great example of multi-line sed editing in the last one.

Remove Unused Assets from a Cinelerra XML Project File

This is a bash script to remove all the unwanted assets from a Cinelerra project XML file. I needed it to cut out bloat from a project I was working on which had hundreds of unused resources after I split the project up into ten minute chunks. Doing so stopped Cinelerra from crashing when I loaded the project: YMMV.

Save this script as “remove_unused_assets.sh”. It needs the function in “list_unused_assets.sh” which I posted here.

#! /bin/bash
#kk remove_unused_assets.sh
#kk
#kk For cinelerra xml files
#kk this script removes the contents of asset tags which are not also used for edits

if [ -z "$1" -o "$1" = "-h" ]
then
echo “Usage: remove_unused_assets [xml_filename]“
echo “For cinelerra xml files, this script removes the contents of asset tags which are not being used for edits”
exit
fi

TMPDIR=”/tmp”
SCRIPTDIR=”$HOME/Video/video_new/common/scripts”

. $SCRIPTDIR/list_unused_assets.sh
. $SCRIPTDIR/include.inc

#assign the parameter to a variable
XMLFILE=$1

#location of the temporary files
ASSETS_FILE=”$TMPDIR/ASSETS_FILE”
EDITS_FILE=”$TMPDIR/EDITS_FILE”
XMLFILE_NEW=”$1″_new
XMLFILE_TMP=”$TMPDIR/XMLFILE_TMP”

#check if the xml file exists and exit if it does not
if [ ! -e $XMLFILE ]; then error “XML file does not exist”; fi

list_unused_assets $XMLFILE
if [ $? != 0 ] ; then error “list_unused_assets failed”; fi

cp $XMLFILE $XMLFILE_TMP

echo
echo Removing Unused Assets…
echo
echo “Working…”
echo

# loop through the list of unused assets and remove the ASSET tag lines for each
# sed command from here: http://ilfilosofo.com/blog/2008/04/26/sed-multi-line-search-and-replace/

for f in $( comm -23 $ASSETS_FILE $EDITS_FILE ); do

#to make the filename string work in sed, I have to escape all of the periods and slashes
FORMATTED_f=`echo “$f” | sed -e ‘s:\/:\\\/:g’ -e ‘s:\.:\\\.:g’`

#this complicated sed script came from the sed FAQ: http://sed.sourceforge.net/sedfaq4.html#s4.21
#in order to make the variable substitution work, I had to close the sed script with a single quote
#then enclose the variable in double quotes, then re-open the sed script with a single quote
#the -i option is for editing a file “in place”
sed -i -e ‘
# sed script to delete a block if /regex/ matches inside it
:Top
/\/ { # For each line between these block markers..
/\/ASSET\>/!{ # If we are not at the /end/ marker
$!{ # nor the last line of the file,
N; # add the Next line to the pattern space
b Top
} # and branch (loop back) to the :Top label.
} # This line matches the /end/ marker.
/’”$FORMATTED_f”‘/d; # If /regex/ matches, delete the block.
} # Otherwise, the block will be printed.
#—end of script—
‘ $XMLFILE_TMP

#diff $XMLFILE $XMLFILE_TMP

echo -n ‘ \r’
echo -n $f’\r’

done

cp $XMLFILE_TMP $XMLFILE_NEW

echo
list_unused_assets $XMLFILE_NEW

echo
echo Finished.
echo
echo The new version of the xml file has been saved as $XMLFILE_NEW.
echo

This program depends on include.inc which contains the following:

#!/bin/bash

#use colour in the output just for fun
GREEN=$(printf “\033[32m”)
RED=$(printf “\033[31m”)
NC=$(printf “\033[0m”)

error()
{
echo ERROR: $1
exit 1
}

I tried to make these scripts as tidy and portable as possible — you will, however, need to change the path for $SCRIPTDIR to the location you are using (and $TMPDIR if you don’t want to put your temporary files in /tmp).

List Unused Assets in a Cinelerra XML Project File

This is a bash script which contains a function used to figure out which assets in a Cinelerra project are not required for the edit list. I created it because I had pulled in a couple of thousand media resources for a project and wanted to eliminate bloat. I moved the project and found it kept crashing on me until I eliminated the crud. I wrote another program to call this function and then actually clean out the xml. You can view “remove_unused_assets.sh” here.

Running this script doesn’t do anything until you call the enclosed function. This function can be called from the command line with:

. list_unused_assets.sh;list_unused_assets
#! /bin/bash
#kk list_unused_assets.sh
#kk
#kk check a cinelerra xml file to see which assets have been loaded, but not used in the project
#kk provide filename to check as parameter
#kk from the command line, type “. list_unused_assets.sh;list_unused_assets

list_unused_assets()
{

SCRIPTDIR=”$HOME/Video/video_new/common/scripts”
TMPDIR=”/tmp”

. $SCRIPTDIR/include.inc

#location of the temporary files
ASSETS_FILE=”$TMPDIR/ASSETS_FILE”
EDITS_FILE=”$TMPDIR/EDITS_FILE”

#assign the parameter to a variable
XMLFILE=$1

#check if the xml file exists and exit if it does not
if [ ! -e $XMLFILE ]; then error “XML file does not exist”; fi

#if the temp file exists, delete it
if [ -e $ASSETS_FILE ]; then
rm $ASSETS_FILE
fi

if [ -e $EDITS_FILE ]; then
rm $EDITS_FILE
fi

echo
echo Checking $XMLFILE for assets unused by the project…
echo

#find all of the filenames in the xml file and strip the extra junk
grep -E “ASSET SRC=” $XMLFILE | sed -e ‘s/^.*SRC=”//g’ -e ‘s/”>.*$//g’ | sort | uniq > $ASSETS_FILE
grep -E “FILE SRC=” $XMLFILE | sed -e ‘s/^.*SRC=”//g’ -e ‘s/”>.*$//g’ | sort | uniq > $EDITS_FILE

#output the counts
echo `grep -E “ASSET SRC=|FILE SRC=” $XMLFILE | sed -e ‘s/^.*SRC=”//g’ -e ‘s/”>.*$//g’ | sort | uniq | wc -l` Total Assets
echo $RED`comm -23 $ASSETS_FILE $EDITS_FILE | wc -l` Unused Assets$NC
echo $GREEN`comm -12 $ASSETS_FILE $EDITS_FILE | wc -l` Used Assets$NC

}

This program depends on include.inc which contains the following:

#!/bin/bash

#use colour in the output just for fun
GREEN=$(printf “\033[32m”)
RED=$(printf “\033[31m”)
NC=$(printf “\033[0m”)

error()
{
echo ERROR: $1
exit 1
}

I tried to make these scripts as tidy and portable as possible — you will, however, need to change the path for $SCRIPTDIR to the location you are using (and $TMPDIR if you don’t want to put your temporary files in /tmp).

Test File Paths in a Cinelerra XML File

This is a bash script to test all the filenames and paths in a Cinelerra project to make sure they are still valid.

#!/bin/bash
#kk test_xml_paths.sh
#kk
#kk check a cinelerra xml file to make sure the file references are all valid
#kk provide filename to check as parameter

if [ -z "$1" -o "$1" = "-h" ]
then
echo “Usage: test_xml_paths [xml_filename]“
echo “For cinelerra xml files, this script checks that file paths are valid”
exit
fi

SCRIPTDIR=”$HOME/Video/video_new/common/scripts”
TMPDIR=”/tmp”

. $SCRIPTDIR/include.inc

#assign the parameter to a variable
XMLFILE=$1

#check if the xml file exists and exit if it does not
if [ ! -e $XMLFILE ]; then error “XML file does not exist”; fi

#location of the temporary file
FILENAMES=”$TMPDIR/TEST_XML_PATHS”

#set counters to zero
GOODCOUNT=0
BADCOUNT=0

#if the temp file exists, delete it
if [ -e $FILENAMES ]; then
rm $FILENAMES
fi

echo
echo Checking $XMLFILE for valid file paths…
echo

#find all of the filenames in the xml file and strip the extra junk
#send the output to a file
grep -E “SRC=|PATH=” $XMLFILE | sed -e ‘s/^.*SRC=”//g’ -e ‘s/^.*PATH=”//g’ -e ‘s/”>.*$//g’ > $FILENAMES
if [ $? != 0 ] ; then error “grep failed”; fi

# loop through the output and test if the filename is either a link or a file
for f in $( cat $FILENAMES ); do
if [ ! -h $f -a ! -e $f ]; then
BADCOUNT=`expr $BADCOUNT + 1`
echo ERROR: Missing $f
else
GOODCOUNT=`expr $GOODCOUNT + 1`
fi
done

#output the counts
echo
echo $RED$BADCOUNT Total Bad Pathss $NC
echo $GREEN$GOODCOUNT Total Good Paths$NC
echo

This program depends on include.inc which contains the following:

#!/bin/bash

#use colour in the output just for fun
GREEN=$(printf “\033[32m”)
RED=$(printf “\033[31m”)
NC=$(printf “\033[0m”)

error()
{
echo ERROR: $1
exit 1
}

I tried to make these scripts as tidy and portable as possible — you will, however, need to change the path for $SCRIPTDIR to the location you are using (and $TMPDIR if you don’t want to put your temporary files in /tmp).

Creating Subtitles/Captions for a Video Project

I’m working on a quick 20 minute video for a non-profit group (and I do mean quick — less than two weeks from initial contact to the premiere). Everything has come together pretty nicely and I’ve finished the editing to my satisfaction in Cinelerra. Because some of the interviewees in the video have impaired speech, we’ve decided that it would be good to add subtitles in English to help viewers to follow the audio. Since we don’t want to stigmatize the people with the speech difficulties, I’m subtitling the whole video. This is fine since it isn’t too long. In any case, it also has the benefit of making the video accessible to the hard of hearing.

Rather than use Cinelerra’s title effect to add the captions, I decided to teach myself how to do it the “proper” way with a separate subtitle file.

Transcribing the Subtitles

Surprisingly, it isn’t completely obvious how and when to place the subtitles in the video. How long should they appear on screen? Should they be synchronized precisely with the video? How do you punctuate people’s verbal stream-of-consciousness ramblings? Do you include the speaker’s pauses and “um”s and so on? What do you do about words you simply cannot decipher? There’s lots of technical info out there on closed captioning, but not much in the way of tips for the beginner who is creating do-it-yourself video. The best synopsis I could find was a quote from this thread about live streaming closed captioning:

The real keys are timing and readability. Captioning is not just typing what the person is saying. You also decide when the caption appears and disappears. Tying a new caption to a shot change or any sort of movement that indicates that a person is about to speak is a good idea. The idea is that the caption itself should work with the rest of the visuals and not be too distracting. Don’t let any captions be too short or too long either. Right around two seconds a piece is a good rule of thumb. As far as readability, be wary of where you break a sentence if a caption is more than one line long. Again, the idea here is that the captions should flow.

Based on these thoughts, plus some common sense, I’ve devised the following informal guidelines for my project:

1) Try to transcribe precisely all of the actual words. Indicate long pauses by creating a new caption, or with ellipses or whatever punctuation seems appropriate. Ignore interjected particles such as “uh” or “um” unless they seem to be essential to the meaning of the utterance.
2) Synchronize the caption to start and end at the same time as the audio, unless the audio is less than two seconds long, in which case let the caption linger for two seconds.
3) Try to break captions on cuts in the video where possible.
4) Watch out for dramatic conclusions to sentences — keep the parts synchronized separately, so you don’t give away the ending in advance.
5) When a speaker is talking at length, use two line captions as required and try to break on sentence clauses or on pauses in the speech. Shorter is usually better.

Creating the Subtitle File

The technical process of creating subtitles is fairly easy, if tedious. I used the subtitleeditor application (tips here and here and here) which can be easily installed in Ubuntu to transcribe most of the titles. Unfortunately, I found it frustrating that the application sometimes seemed to arbitrarily ignore what I had typed, forcing me to re-enter all or most of many subtitles. Just for this step, I switched to the “Gaupol Subtitle Editor” which worked much the same way and didn’t seem to have the same bug. Next time, I’d investigate using a spreadsheet and then importing the data into the subtitle editor program. I found that transcribing and synchronizing had to be done as two separate steps anyhow.

For the synchronizing, I found the easiest method was to go back to the first Subtitle Editor app, use it to generate a waveform from the audio track of my video, then use the mouse and keyboard to set the correct start and end points for each subtitle. I set the “play/pause” shortcut to Super (Windows key) plus space, “short” (skip backward) to Super-left arrow, and “short” (skip forward) to Super-right arrow (yes, there are two keyboard shortcuts with the same name, but you can tell which is which by clicking on them in the shortcuts preferences). The default is for left-mouse-click to set the start point for the selected subtitle line, and right-mouse-click to set the end point.  Middle-click restarts the playback at the point in the wave timeline where you clicked.  Since I already had all the words transcribed, I just had to run through the audio track, listening and watching the waveform graph, using the shortcuts to move around, and click to select the right in and out points for each line. I found I had to split some of the subtitles, but that was also easy using the Subtitle Editor tool.  Overall, synchronization went pretty smoothly.

There are many different subtitle formats, but the default format worked fine for me.

Combining the Subtitles with the Video

According to the Cinelerra manual, there are three obvious choices for combining subtitles with your video:

# Distribute it with your video. People will have to load the appropriate subtitle file in their video player to actually see the subtitles.
# Use it with dvdauthor, to add the subtitles in a DVD. Read dvdauthor’s documentation for more information.
# Incrust the subtitles into the video using mencoder.

I used the second method, which seems to be the most flexible option, but also the most complicated.  In my case, I wanted to force the subtitles to appear rather than allowing the user to select whether to play them.  Dvdauthor provides a tool called spumux, which allows you to add a subtitle track to the video.  Then, you use dvdauthor (as you normally would) to build the dvd filesystem.   From there, the process is the same as for burning a non-subtitled video (I’ll write up my own process at some point, but there’s already a very good explanation from Crazed Mule: look here for exporting from Cinelerra and look here for creating a DVD).  You’ll need to create an xml file for spumux and another for dvdauthor.

Here is my subtitle xml file for the first step:

<subpictures>
<stream>
<textsub filename=”/home/kevin/Video/video_ykacl/project_xml/en_subtitles.sub” characterset=”UTF-8″
fontsize=”32.0″ font=”Arial.ttf”
horizontal-alignment=”center”
vertical-alignment=”bottom” left-margin=”60″
right-margin=”60″
top-margin=”20″ bottom-margin=”30″ subtitle-fps=”29.97″
movie-fps=”29.97″ movie-width=”720″ movie-height=”480″
force=”yes”/>
</stream>
</subpictures>

Note that for spumux to work, you MUST have copy or symbolic link to the truetype font file (in this case, Arial.ttf, but use whatever you like) in the .spumux folder in your home directory. I did it by running this command:

ln -s /usr/share/fonts/truetype/msttcorefonts/Arial.ttf /home/kevin/.spumux/Arial.ttf

The above command assumes you have the msttcorefonts package installed.  Also note the force=”yes” option, which tells the dvd player to always display these subtitles.

Once you’ve created the xml, you run spumux to combine your subtitle file with your video:

spumux -s0 $VIDEO_PROJECT/project_xml/en_subtitles.xml < $VIDEO_TMP/full_render.mpg > $VIDEO_TMP/full_render_subtitle.mpg

I put this command in a script in which I defined $VIDEO_PROJECT and $VIDEO_TMP — you can subsitute whatever path is appropriate.

Now you need to create another xml file for dvdauthor to use when building the dvd menu and filesystem (in my case the video is supposed to play automatically, so there is no actual menu):

<dvdauthor>
<vmgm />
<titleset>
<titles>
<subpicture lang=”en” />
<pgc>
<pre> subtitle=64; </pre>
<vob file=”/home/kevin/Video/video_tmp/video_ykacl_tmp/full_render_subtitle.mpg” />
</pgc>
</titles>
</titleset>
</dvdauthor>

The most important option in this file is the subtitle=64, which tells the dvd player to automatically display subtitle track 0 (see the links below for details on this). Now you just run dvdauthor:

dvdauthor -o dvd/ -x $VIDEO_PROJECT/project_xml/dvdauthor.xml

At this point you should have a working dvd filesystem ready to be burned onto an actual dvd. Before burning, you can test your output by running

vlc dvd:///path/to/dvd/

More Information About Subtitles

Explanation of how to add subtitles in dvdauthor is here.

Useful details on spumux is here.

Good examples here.

Looking at Video File Metadata

Three choices as per the details here:

tcprobe -i filename
ffmpeg -i filename
midentify filename

Info on file types here.

I’m trying to understand video formats to make it easier to transcode for various purposes. I’ve found some useful links:

adamwilt.com > the DV, DVCAM & DVCPRO Formats

HDV vs HD: A Primer

Digital Video Formats and Video Conversion Explained

Video File Formats 101 : Formats Explained