Notes

  • DvdMedia. List of most reliable DVD media brands.

Audio Book Recoding

mkfifo fifo.wav # named pipe, recommended by mplayer developers
mplayer -af resample=32000:0:2,pan=1:0.5:0.5,volnorm=2,format=s16ne \
  -ao pcm:file=fifo.wav file.mp3 # output to named pipe, start this process 1st
# May need to implement input file sample rate testing.  Also, not good resampling.
# Best resampler is Shibatch Audio Tools http://shibatch.sourceforge.net/
# See review at http://www.mainly.me.uk/resampling/index.html
speexenc --vbr --dtx --denoise fifo.wav file.spx # run after mplayer started
# defaults best compromise for speex, but with added above prefilters
# Sample file sizes: spx as above = 4.6 MB, spx q10 = 7.0MB, ogg q-1 = 6.8MB (bad)
# spx q8 no resample = 6.1MB (not better); starting file 44.1KHz 170Kbps MP3 = 35.8

Audio Book Ripping Script

Rips simultaneously from three drives in parallel. Backgrounds encoding process.
#!/usr/bin/perl
use strict;
use warnings;
use threads;
use Thread::Queue;
use Thread::Semaphore;
use YAML::XS qw(LoadFile);

my $d = LoadFile 'data.yml';
my $encoding_threads = 3;
my @drives = qw(/dev/cdrom0 /dev/cdrom1 /dev/cdrom2);

my $semaphore = new Thread::Semaphore;

print "--- Ripping \"$$d{title}\" ---\n";

my $encode_queue = Thread::Queue->new();
my @enc_thr; # Holds speex process threads
for (1..$encoding_threads) {
   my $thr = async {
      while (defined(my $encodejob = $encode_queue->dequeue())) {
         &encode($encodejob);
      }
   };
   push @enc_thr, $thr;
}

my $read_queue = Thread::Queue->new();
$read_queue->enqueue( $$d{starting_disc}..$$d{num_discs} );
$read_queue->enqueue( (undef) x (scalar @drives) );
my @read_thr;
for my $drive (@drives) {
   my $thr = async {
       while (defined(my $disc = $read_queue->dequeue())) {
         &read($drive, $disc);
         $encode_queue->enqueue($disc);
      }
   };
   push @read_thr, $thr;
   &small_sleep(0.1);
}

$_->join for (@read_thr);
$encode_queue->enqueue( (undef) x $encoding_threads );
print "Waiting for background encoding threads to finish...\n";

$_->join for (@enc_thr);
`eject $_` for (@drives);
print "Done\n";

sub read {
    my ($drive, $disc) = @_;
    my @track_groups = split /\n/, $$d{track_groups};
    $semaphore->down;
   print("Please insert disc $disc\n");
    qx(eject $drive);
   # Wait until disc inserted:
    sleep 1 while (&rip($drive, "-1:[1.1]", "/dev/null"));
    $semaphore->up;
    #sleep 2;
    for my $t (@track_groups) {
      sleep 1 while (&rip($drive, $t, "$disc.$t.wav"));
   }         
}


sub rip {
   my ($drive, $tracks, $filename) = @_;
   open STDERR, ">>/dev/null";
   return system("cdparanoia", "-q", "-Z", "-d", "$drive", "--", 
         "$tracks", "$filename");
   close STDERR;
}


sub encode {
    my ($disc) = shift(@_);
   for my $aref (&meta($disc)) {
      my ($filename, $spx, @comments) = @$aref;
      &downmix($filename);
      &normalize($filename);
      &resample($filename);
      &speex(@$aref);
   }
}


# Takes $disc as input, returns .wav filename, .spx filename,
# followed by list of comments as an arrayref for each track group.
sub meta {
    my ($disc) = shift(@_);
   my @list = split /\n/, $$d{chapters};
   my @track_groups = split /\n/, $$d{track_groups};
   my $num_lectures = sprintf("%02d", scalar @list);
   my $outdir = "$$d{title} ($$d{year})";
   my @output_array;
    for my $i (0..@track_groups) {
      my $lecture_num = sprintf("%02d", ($disc-1)*@track_groups + $i + 1);
      my $filename = "$disc.$track_groups[$i].wav";
      my @comments = ("Title=$list[$lecture_num -1]", 
                  "Artist=$$d{author}", 
                  "Album=$$d{title}", 
                  "Date=$$d{year}", 
                  "Track Number=$lecture_num of $num_lectures",
                  "Genre=Speech",
                  "Comment=$$d{comment}");
      mkdir("$$d{title} ($$d{year})");
      my $spx = "$$d{title} ($$d{year})/" .
              "($lecture_num.$num_lectures) $list[$lecture_num - 1].spx";
      push(@output_array, [$filename, $spx, @comments]);   
   }
   return @output_array;
}
      

sub speex {
      my ($filename, $spx, @comments) = @_;
      my @cmd = qw(nice ionice -c3 speexenc --vbr --dtx);
      for my $c (@comments) {
         push(@cmd, ("--comment", "$c"));
      }
      push(@cmd, ("$filename", "$spx"));
      my $e = system(@cmd);
      unlink("$filename") if (! $e);
      return $e;
}


sub downmix {
   my $filename = shift(@_);
   my $e = system("nice", "sox", "$filename", 
               "mono_$filename", "channels", "1");
   rename("mono_${filename}", "$filename");
   return $e;
}      


sub normalize {
   my ($filename) = shift(@_);
   my $e = system("nice", "normalize-audio", "-q", "$filename");
   return $e;
}


sub resample {
   my $filename = shift(@_);
   my $e = system("nice", "ssrc", "--quiet", "--twopass", "--rate", 
               "32000", "$filename", "resample_$filename");
   rename("resample_${filename}", "$filename");
   return $e;
}   


sub small_sleep {
   select(undef, undef, undef, shift(@_) );
}

Alsa A52 real-time encoding

Requires soundcard with s/pdif out.
  1. Install following:
    aptitude install libavcodec-unstripped-52 libavcodec-dev
  2. Download alsa-plugins source.
  3. Extract in /usr/src
  4. ./configure && make
  5. copy ./a52/.lib/*.so /usr/lib/alsa-lib/

Cheat Sheets

Important Experimental Conclusions

  • ffmpeg for aac encoding scrambles channel mapping when played back with mplayer
  • nero and holyroses script for aac encoding keeps channels correct
  • aften keeps channels correct for AC3 encoding
  • aften vbr encoding works on integra, but seeeming stream errors in beginning
  • aften cbr works perfectly with defaults using wav as input
  • eac3to for 5 -> 2ch PL downmix is OK, but slow encoding
  • handbrake can't do audio only, and crashes if nonexistant subtitle is selected
  • real-time a52 encoding at 640kbps with alsa and playback of 6 channel wav of aac results in perfect sound, if using nero AAC encoder. Initially there were some problems with slow video, but this was fixed with a reboot and ensuring resample to 48k always included in filter chain. FFmpeg would probably work as well, but channel mapping is not correct.
  • DTS to AC3 encoding works well with ffmpeg -> aften pipe, but ffmpeg has difficulty with dts output to file only. Therefore use ffmpeg input.mkv -f wav - | aften - out.ac3
  • playback of AAC 5-channel sources is barely acceptable with mplayer -channels 2 option
  • playback of AAC 2-channel sources is perfect (sent to integra as PCM)

Initial Mythbuntu (ash) Customizations

echo "Port 22003" >> /etc/ssh/sshd_config
ssh linode "allsystemsgo"
cp commtrim fill_mythvideo_metadata.pl hdhomerun_config* jamu.py music myth* prepbackup.ash restartx /usr/local/bin/
alsamixer # Set digital SPDIF to on
cat <<'EOF'>/etc/X11/xorg.conf
Section "Device"
   Identifier   "Default Device"
   Driver      "intel"
   Option          "XvMC"  "true" 
EndSection
EOF
#!/bin/sh
cat <<'EOF'>/usr/local/bin/lircstart.sh
/etc/init.d/lirc stop
sleep 1
killall > /dev/null 2>&1
sleep 1
lircd --driver=devinput --device=/dev/input/by-id/usb-Gyration_Gyration_RF_Technology_Receiver-event-kbd \
  --pidfile=/var/run/lirc1.pid --listen=9988 --output=/var/run/lirc/lircd;
lircd --driver=devinput --device=/dev/input/by-id/usb-Gyration_Gyration_RF_Technology_Receiver-event-mouse \
  --pidfile=/var/run/lirc2.pid --connect=localhost:9988;
EOF

# /etc/init.d/lirc patch
cp /etc/init.d/lirc /etc/init.d/lirc.dist

--- lirc.dist   2010-03-28 23:46:57.233064001 -0500
+++ lirc.gyration   2010-03-28 23:46:57.233064001 -0500
@@ -167,6 +167,12 @@
          else
             log_end_msg 1
          fi
+         # Hack to get Gyration mouse events working
+         killall lircd >/dev/null 2>&1
+         lircd --driver=devinput --device=/dev/input/by-id/usb-Gyration_Gyration_RF_Technology_Receiver-event-kbd \
+             --pidfile=/var/run/lirc1.pid --listen=9988 --output=/var/run/lirc/lircd;
+         lircd --driver=devinput --device=/dev/input/by-id/usb-Gyration_Gyration_RF_Technology_Receiver-event-mouse \
+             --pidfile=/var/run/lirc2.pid --connect=localhost:9988;
       fi
 
       if [ "$START_LIRCMD" = "true" ]; then
@@ -194,10 +200,13 @@
          log_daemon_msg "Stopping remote control mouse daemon: LIRCMD"
          start-stop-daemon --stop --quiet --exec /usr/sbin/lircmd
          log_end_msg $?
+         # Hack to get Gyration mouse events working
+         killall lircd >/dev/null 2>&1
       fi
 
       if [ "$START_LIRCD" = "true" ]; then
          log_daemon_msg "Stopping remote control daemon(s): LIRC"
+
          start-stop-daemon --stop --quiet --exec /usr/sbin/lircd
          log_end_msg $?
          [ -h "$OLD_SOCKET" ] && rm -f $OLD_SOCKET


echo "/usr/lib/libIntelXvMC.so" > /etc/X11/XvMCConfig
echo "/mnt/dv    *(ro,async,no_root_squash,no_subtree_check)" > /etc/exports
dpkg -i nxclient_3.4.0-5_x86_64.deb 
dpkg -i nxnode_3.4.0-11_x86_64.deb 
dpkg -i nxserver_3.4.0-12_x86_64.deb

# Files and Directories to restore
/home/rde/.lirc
/home/rde/.lircrc
/etc/lirc
/etc/asound*
/mnt/* #symlinks
/usr/local/bin/integra, music, integra-query

# To bundle all of the above:
tar czPf mythbuntu_9.10_tweaks.tar.gz /etc/ssh /usr/local/bin/commtrim \
/usr/local/bin/fill_mythvideo_metadata.pl /usr/local/bin/hdhomerun_config* \
/usr/local/bin/jamu.py /usr/local/bin/music /usr/local/bin/prepbackup.ash /usr/local/bin/restartx \
/usr/local/bin/integra* /etc/X11/xorg.conf /usr/local/bin/lircstart.sh /etc/init.d/lirc.gyration \
/etc/init.d/lirc /etc/X11/XvMCConfig /home/rde/.lirc* /etc/lirc/ /etc/asound* /mnt/home /mnt/bulk \
/mnt/n1000d /mnt/n500d /mnt/working /root/.bashrc /etc/auto.* /etc/sudoers /etc/apache2/htdigest_master \
/etc/apache2/htaccess_master /home/rde/.bashrc /root/.ssh /home/rde/.ssh \
/etc/ntp.conf /etc/ssl /usr/local/bin/harshpurge /usr/local/bin/myth* /usr/local/bin/*perms \
/usr/lib/alsa-lib/libasound_module_pcm_a52.* /etc/mplayer/mplayer.conf \
--exclude '/etc/ssl/certs'

# Playing 1280p files is difficult.  Following options work:
mplayer -vfm ffmpeg -lavdopts lowres=1:fast:skiploopfilter=all -fs filename.mkv

Optimized Media Encoding and Transcoding

# Use mythtranscode to cut out commercials (make cutlist first)
mythtranscode -m -c chanid -s starttime -l -o output.mpg

# Extract closed captioning
ccextractor -utf8 mpeg2.mpg -o output.srt

# CRF (Constant quality, x264 specific setting; 26 recommended highest, but 32 much smaller files)
# After experimentation, a crf of 30 is near source qualty on 720p HD.
# Preset -vpre hq results in smaller file size, takes ~ 3x file duration for 720p. -vpre normal ~ 1x duration.
# The option -vsync 1 was tried, but causes audio sync skew.
# Specifying the rate as 30000/1001 decreases file size by about 20% from 59.94fps.
# A mp4 container can be used, but the whole file must be complete to play it.
# The map paramaters select which streams are to be encoded (0 video and 2 audio below)
ffmpeg -y -i mpeg2input.mpg -r 30000/1001 -map 0:0 -vcodec libx264 -crf 30 -vpre normal -map 0:2 \
  -acodec copy -threads 0 output.mkv

# If program is stereo, can use the following to copy audio into ogg vorbis @ about 90kbps:
-acodec vorbis -aq 25 -ac 2

# File size trials with various parameters:
# Source ATSC mpeg2 720p 24 episode: 4.5G
# crf vpre rate size(MB) qual
# --- ---- ---- -------- ----
# 26  hq   60   922      perfect
# 28  nl   60   751      excellent
# 28  hq   30   592      excellent
# 30  hq   60   589      good
# 30  nl   60   683      good
# 30  nl   30   478      good
# 32  hq   60   356      fair

# Add srt subtitles to existing mkv file
# The charset and language info is forced with the options below
mkvmerge -v -o output.mkv --language 1:eng --language 2:eng input.mkv --language 0:eng subtitles.srt

# Handbrake can do the same with a single command, and has advantages of automatic decomb filtering.
# The following command sets maximum resolution to 1280 width or 720 height, and copies all subtitiles.
# This is a universal command that should be suitable for any MPEG2 or MPEG4 with resolution > 720p:
HandBrakeCLI -e x264 -q 26.0 --decomb --detelecine --loose-anamorphic -X 1280 -Y 720 \
  -m -x b-adapt=2:rc-lookahead=50 -s 1,2,3,4,5,6,7,8,9,10 -N eng -i infile.mpg -o outfile.mkv

Obsolete Media Encoding Methods

# Two pass MPEG2 (ATSC) to MPEG4 (H.264), keeping audio (AC3) stream untouched.
# Obsolete since crf gives better results.
ffmpeg -y -i mpeg2input.mpg -r 30000/1001 -b 2M -bt 4M -vcodec libx264 -pass 1 -vpre fastfirstpass -an -vn -threads 0 
ffmpeg -y -i mpeg2input.mpg -r 30000/1001 -b 2M -bt 4M -vcodec libx264 -pass 2 -vpre hq -acodec copy  output.mkv

# Audio above just keeps AC3.  MPEG4 container requires AAC.  AAC can be compressed with various settings,
# including the switch "-aq [0-255]" (undocumented) to specify quality.  Trials verified that compression of 5.1 ac3
to 5.1 aac destroys quality without saving much space.  The map option is used to specify audio an video streams to encode.
ffmpeg-y -i mpeg2input.mpg -r 30000/1001 -crf 36 -map 0:0 -vcodec libx264 -map 0:2 -acodec libfaac -ab 224k -threads 0 output.mpg

MythTV Commercial Cut Script

#!/bin/bash

### removecommercials - for mythtv user job.
### $author Zack White - zwhite dash mythtv a t nospam darkstar deleteme frop dot org
### $Modified 20080330 Richard Hendershot - rshendershot a t nospam gmail deleteme dot youknowcom
### $Modified 20100112 Aaron Larson to get password from mythtv config file, clear autoskip list after transcoding, and detect pre-flagged files.

# Should be set as a mythtv user job with a command as:
#  removecommercials %DIR% %FILE% %CHANID% %STARTTIME% 
#
#   initialize;  all except SKIP are required for this to function correctly
declare VIDEODIR=$1
declare FILENAME=$2
declare CHANID=$3
declare STARTTIME=$(echo $4 | sed -e 's/\([0-9]\{4\}\)\([0-9]\{2\}\)\([0-9]\{2\}\)\([0-9]\{2\}\)\([0-9]\{2\}\)\([0-9]\{2\}\)/\1-\2-\3-\4-\5-\6/')
declare SKIP=$5
# for lossless transcoding autodetect.  Set to empty string for rtJpeg/mpeg4.
declare MPEG2=--mpeg2
declare PROG=$(basename $0)

if [ -z "${VIDEODIR}" -o -z "${FILENAME}" -o -z "${CHANID}" -o -z "${STARTTIME}" ]; then
        cat - <<-EOF
   Usage: $PROG <VideoDirectory> <FileName> <ChannelID> <StartTime> [SKIP]

   Flag commercials (if they are not already flagged), do a lossless transcode
   to remove the commercials, and fixup the database as necessary.    The net
   effect is that this script can be run as the *only* job after a recording,
   or as a job after a commercial flagging job (either way).  The optional 5th
   parameter 'SKIP', if specified as a non zero length string, will transcode
   using the existing cutlist.
   EOF
        exit 5
fi
if [ ! -f "${VIDEODIR}/${FILENAME}" ]; then
        echo "$PROG: File does not exist: ${VIDEODIR}/${FILENAME}"
        exit 6
fi
if [ ! -d "${VIDEODIR}" ]; then 
        echo "$PROG: <VideoDirectory> must be a directory"
        exit 7
fi
if [ ! -d "${VIDEODIR}/originals" ]; then 
        mkdir "${VIDEODIR}"/originals
fi
if [ ! -d "${VIDEODIR}/originals" ]; then 
        echo "$PROG: you must have write access to <VideoDirectory>"
        exit 8
fi

# mythtv stores the mysql configuration information in the following
# file.  Extract the DB user and password.
mythConfig=~/.mythtv/config.xml 
mysqlArgs=""
if [ -e "$mythConfig" ]; then
        mysqlUserOpt=$(sed $mythConfig -n -e '/<DBUserName/p')
        if [ -n "$mysqlUserOpt" ]; then
           mysqlUser=$(echo $mysqlUserOpt | sed 's: *</*DBUserName> *::g')
           mysqlArgs+=" -u $mysqlUser"
        fi
        mysqlPassOpt=$(sed $mythConfig -n -e '/<DBPassword/p')
        if [ -n "$mysqlPassOpt" ]; then
           mysqlPass=$(echo $mysqlPassOpt | sed 's: *</*DBPassword> *::g')
           if [ -n "$mysqlPass" ]; then 
               mysqlArgs+=" -p$mysqlPass"
           fi
        fi
fi

if [ -z "${SKIP}" ]; then
        #   if transcode was run after mythcommflag in the normal setup screens
        #   then the current file may not match the existing index, so rebuild
        echo "$PROG: Rebuilding seek list for ${FILENAME}"
        mythcommflag -c ${CHANID} -s ${STARTTIME} --quiet --rebuild
        ERROR=$?
        if [ $ERROR -ne 0 ]; then
                echo "$PROG: Rebuilding seek list failed for ${FILENAME} with error $ERROR"
                exit $ERROR
        else
                echo "$PROG: Rebuilding seek list successful for ${FILENAME}"
        fi

        #   flag commercials (generate skiplist)
        #   you can use mythcommflag -f ${VIDEODIR}/${FILENAME} --getskiplist
        #   to view results
   
   # has mythcommflag already run?
   alreadyFlagged=$(mysql $mysqlArgs -B -N -e "select commflagged from recorded where basename = '${FILENAME}'" mythconverg)
   if [ "$alreadyFlagged" == "1" ]; then
       echo "$PROG: ${FILENAME} already flagged, skipping mythcommflag."
   else
       echo "$PROG: Commercial flagging ${FILENAME}"
       mythcommflag -c ${CHANID} -s ${STARTTIME} --quiet 
       ERROR=$?
       if [ $ERROR -gt 126 ]; then
          echo "$PROG: Commercial flagging failed for ${FILENAME} with error $ERROR"
          exit $ERROR
       else
          echo "$PROG: Commercial flagging successful for ${FILENAME}"
       fi
   fi

   #   generate cutlist from skiplist
   #   you can use mythcommflag -f ${VIDEODIR}/${FILENAME} --getcutlist
   #   to view results
   echo "$PROG: Creating cutlist from skiplist for ${FILENAME}"
   mythcommflag -c ${CHANID} -s ${STARTTIME} --quiet --gencutlist
   ERROR=$?
   if [ $ERROR -ne 0 ]; then
      echo "$PROG: Creating cutlist from skiplist failed for ${FILENAME} with error $ERROR"
      exit $ERROR
   else
      echo "$PROG: Creating cutlist from skiplist successful for ${FILENAME}"
   fi
else
        echo "$PROG: skipping commercial detection due to parameter $SKIP"        
fi  #end skip

#   cut the commercials from the file.  creates a new file and a map file.
echo "$PROG: Transcoding commercials out of original file (${FILENAME})"
mythtranscode -c ${CHANID} -s ${STARTTIME} $MPEG2 --honorcutlist -o "${VIDEODIR}/${FILENAME}.mpeg"
ERROR=$?
if [ $ERROR -ne 0 ]; then
        echo "$PROG: Transcoding failed for ${FILENAME} with error $ERROR"
        exit $ERROR
else
        echo "$PROG: Transcoding successful for ${FILENAME}"
fi

echo "$PROG: Moving ${VIDEODIR}/${FILENAME}  to  ${VIDEODIR}/originals/${FILENAME}"
mv "${VIDEODIR}/${FILENAME}" "${VIDEODIR}/originals"
ERROR=$?
if [ $ERROR -ne 0 ]; then
        echo "$PROG: Moving failed with error $ERROR"
        exit $ERROR
else
        echo "$PROG: Moving successful"
fi

echo "$PROG: Moving ${VIDEODIR}/${FILENAME}.mpeg  to  ${VIDEODIR}/${FILENAME}"
if [ ! -f "${VIDEODIR}/${FILENAME}" ]; then
        mv "${VIDEODIR}/${FILENAME}.mpeg" "${VIDEODIR}/${FILENAME}"
        ERROR=$?
        if [ $ERROR -ne 0 ]; then
                echo "$PROG: Moving failed with error $ERROR"
                exit $ERROR
        else
                echo "$PROG: Moving successful"
        fi
else
        echo "$PROG: cannot replace original.  skipping file move. (${VIDEODIR}/${FILENAME})"
fi


echo "$PROG: removing map file: ${VIDEODIR}/${FILENAME}.mpeg.map"
if [ -f "${VIDEODIR}/${FILENAME}.mpeg.map" ]; then
        rm "${VIDEODIR}/${FILENAME}.mpeg.map"
        ERROR=$?
        if [ $ERROR -ne 0 ]; then
                echo "$PROG: unable to remove map file: ${VIDEODIR}/${FILENAME}.mpeg.map"
        else
                echo "$PROG: removed map file successfully"
        fi
fi    

#   file has changed, rebuild index
echo "$PROG: Rebuilding seek list for ${FILENAME}"
mythcommflag -c ${CHANID} -s ${STARTTIME} --quiet --rebuild
ERROR=$?
if [ $ERROR -ne 0 ]; then
        echo "$PROG: Rebuilding seek list failed for ${FILENAME} with error $ERROR"
        exit $ERROR
else
        echo "$PROG: Rebuilding seek list successful for ${FILENAME}"
fi

echo "$PROG: Clearing cutlist for ${FILENAME}"
mythcommflag -c ${CHANID} -s ${STARTTIME} --quiet --clearcutlist
ERROR=$?
if [ $ERROR -eq 0 ]; then
        echo "$PROG: Clearing cutlist successful for ${FILENAME}"
else
        echo "$PROG: Clearing cutlist failed for ${FILENAME} with error $ERROR"
        exit $ERROR
fi
        
# mythcommflag sets cutlist to zero, but doesn't update the filesize.
# Fix the database entry for the file
mysql $mysqlArgs mythconverg << EOF 
    UPDATE 
        recorded
    SET
        cutlist = 0,
        filesize = $(ls -l "${VIDEODIR}/${FILENAME}" | awk '{print $5}') 
    WHERE
        basename = '${FILENAME}';
EOF

echo "$PROG: Clearing autoskip list: ${VIDEODIR}/${FILENAME}"
mysql $mysqlArgs mythconverg << EOF 
    DELETE FROM 
      recordedmarkup
    WHERE 
      CONCAT( chanid, starttime ) IN (
         SELECT 
            CONCAT( chanid, starttime )
         FROM 
            recorded
         WHERE 
            basename = '$FILENAME'
      );
EOF

# If you want to keep the originals, comment out this line.
echo "$PROG: removing saved copy of: ${VIDEODIR}/originals/${FILENAME}"
rm "${VIDEODIR}/originals/${FILENAME}"
ERROR=$?
if [ $ERROR -ne 0 ]; then
   echo "$PROG: failed to remove ${VIDEODIR}/originals/${FILENAME}"
   exit $ERROR
fi

Linux Media Applications

List of sites with info on media applications of linux.

Topic attachments
I Attachment Action Size Date Who Comment
elsegz channel.sql.gz manage 4.0 K 13 May 2007 - 04:49 RyanEgeland Chicago Channels SQL File
elsecsv mythtv-chicago-channels.csv manage 13.2 K 13 May 2007 - 04:47 RyanEgeland MythTV? Channels Export from SQL
Topic revision: r20 - 24 Jun 2010 - 17:38:39 - RyanEgeland
 
This site is powered by FoswikiCopyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.