03-16-2009
perl script chokes on dirs with spaces
Basically, I have a perl script that calls enables one to resume where a video file left off (i.e. where the user stopped playback) that chokes on files that are located in a path that contains spaces.
To make the situation a little more complicated, the perl script gets help from a bash script that analyzes the video file in question and passes file-specific switches to mplayer.
Both scripts need to be in the same dir and you must run them from that dir!
Here is the usage:
Code :
$ ./mplayer-resumer-vdpau.pl /path/to/file.avi
(You can use any video format that mplayer can play, like mpg, mkv, etc.)
The problem occurs when the path to the video file contains a space. The perl script doesn't handle it and passes the incorrect options to the file.
Example: I go to play ‘Test.mkv' located in /media/D/New\ CD/
Code :
$ ./mplayer-resumer-vdpau.pl /media/D/New\ CD/Test.mkv
File not found: '/media/D/New'
Failed to open /media/D/New.
File not found: '/media/D/New'
Failed to open /media/D/New.
Can someone have a look at the code and help me fix this? I just don't know that much about perl to be useful.
Code to mplayer-resumer-vdpau.pl
Code :
#!/usr/bin/perl
use Shell;
use strict;
use POSIX qw(floor);
# Written by Bob Igo from the MythTV Store at http://MythiC.TV
# Email: bob@stormlogic.com
#
# If you run into problems with this script, please send me email
# CHANGE LOG:
# 3/9/2009
# Modded Bob's wonderful resumer script to work with the vdpau
# options detector script by nickca of the linhes forums.
#
# http://www.knoppmythwiki.org/index.php?page=HardwareAcceleratedVideo
#
# You need to have both this and the vdpau-detector script in the same
# dir for this to work properly. Also, change your default mplayer
# options in mythfrontend to read simply: # mplayer-resumer-vdpau.pl %s
#
# To tweak the shell commands for mplayer, edit the vdpau-detector script.
# It has a small README inside it as comments
# ENJOY!
# 5/3/2006
# Added last time started checking.
# If this script is restarted within $tdiff (default 5 seconds)
# then it will delete the file used to keep track of the videos
# resume position.
# PURPOSE:
# --------------------------
# This is a wrapper script to prove the concept of having MythTV
# resume playback of previously-stopped video where you left off.
# It's likely that a good solution will look different than this
# initial code.
# RATIONALE:
# --------------------------
# Watching 90% of a video and stopping causes you to return to the
# beginning again the next time you watch it. Remembering where
# you were in the video and resuming at that position is a much nicer
# behavior for the user.
#
# By default, mplayer spits out timecode information that tells you
# where you are in the video, to the tenth of a second. Mplayer also
# supports a seek feature on the command-line. We can make use of these
# features to write an mplayer wrapper that will remember the last
# position in a video file and resume to it on playback.
# PARAMETERS:
# --------------------------
# see print_usage() below
# FILES:
# --------------------------
# $infile, the video to play
# $resumefile, the video's resume file (see get_resume_filename() below)
# KNOWN ISSUES:
# --------------------------
# Mplayer misreports the timecodes on .nuv MPEG-2 files. Currently, anything
# captured via an HDTV tuner card and put into your /myth/video directory
# will fail with this resumer.
#
# Current theories include the timecode having to do with the show's broadcast
# time, recording time, or perhaps its upload time to the station that
# broadcast it.
# DESIGN LIMITATION:
# -------------------------
# If the video file to be played is on a read-only filesystem, or otherwise
# lives in a location that cannot be written to, resume will fail. This is
# because the current implementation uses a file parallel to the video file
# to store the timecode.
#
my $infile;
my $resumefile;
my $mplayer_parameters;
my $fudge_factor=2; # number of additional seconds to skip back before playback
my $tnow; # Time now.
my $tprev; # Time the prog was last started.
# Returned from the modification time of the xx.resume file.
my $tdiff=5; # How many seconds before we should start from
# the beginning of the movie
#DEBUG
#open(DEBUG,">/tmp/debug") || die "unable to open debug file";
sub init () {
$tnow = time();
$infile = @ARGV[$#ARGV];
$resumefile = &get_resume_filename($infile);
# This returns the 9th element of the 13 element array
# created by the stat function.
$tprev = (stat ($resumefile))[9];
# if this file is restarted in less than 5 seconds then
# remove the .resume file
if ( ($tnow - $tprev) < $tdiff ) {
unlink($resumefile);
}
$mplayer_parameters = join(' ',@ARGV[0..$#ARGV-1]);
}
&init();
&save_time_offset(&mplayer($mplayer_parameters,$infile), $resumefile);
#close(DEBUG);
# For $pathname, return $path.$filename.resume
sub get_resume_filename () {
my($pathname)=@_;
my $idx = rindex($pathname,"/");
if ($idx == -1) { # There was no "/" in $pathname
return ".".$pathname.".resume";
} else {
# Now we need to split out the path from the filename.
my $path = substr($pathname,0,$idx+1);
my $filename = substr($pathname,$idx+1);
return "$path.$filename.resume";
}
}
# Calls mplayer and returns the last known video position
sub mplayer () {
my($parameters,$infile)=@_;
my $seconds=0;
my $timecode=&get_time_offset($infile);
my $mplayeropts=`./vdpau-detector $infile`; chomp $mplayeropts;
my @lines = split "\n", $mplayeropts;
my $last_line = pop(@lines);
my $command = "mplayer $last_line $parameters -ss $timecode \"$infile\" 2>&1 2>/dev/null |";
open(SHELL, $command);
# The kind of line we care about looks like this example:
# A:1215.2 V:1215.2 A-V: 0.006 ct: 0.210 207/201 13% 0% 1.9% 0 0 68%
# But all we care to look at is the first number.
while (<SHELL>) {
#print DEBUG $_;
if (m/A: *[0-9]+\.[0-9]/) { # See if this line has timecodes on it
my $last_timecode_line = &extract_last_timecode_line($_);
if ($last_timecode_line =~ m/ *([0-9]+\.[0-9]) V/) {
$seconds=$1;
}
}
}
close(SHELL);
return $seconds;
sub extract_last_timecode_line () {
my ($line)=@_;
my @lines=split('A:',$line);
return @lines[$#lines-1];
}
}
# Save the last known video position
sub save_time_offset () {
my($seconds, $resumefile)=@_;
open(RESUMEFILE, ">$resumefile") || die "Unable to open $resumefile for writing";
print RESUMEFILE "$seconds";
close(RESUMEFILE);
}
# returns the number of seconds corresponding to the last known video position,
# in hh:mm:ss format, compatible with the "-ss" parameter to mplayer
sub get_time_offset () {
my($videofile)=@_;
my($resumefile) = &get_resume_filename($videofile);
my $seconds=0;
my $timecode;
open(RESUMEFILE, "<$resumefile") || return "00:00:00";
while(<RESUMEFILE>) {
$seconds=$_;
}
close(RESUMEFILE);
my $hours = floor($seconds/3600);
$seconds = $seconds - $hours*3600;
my $minutes = floor($seconds/60);
$seconds = int($seconds - $minutes*60) - $fudge_factor;
$timecode = sprintf "%02d:%02d:%02d",$hours,$minutes,$seconds;
# print "TIMECODE: $timecode\n";
return $timecode;
}
sub print_usage () {
print "USAGE:\n";
print "\t",$ARGV[0], "[mplayer parameters] video_file\n";
print "\t","e.g. ",$ARGV[0], "-fs -zoom my.mpg\n";
print "\t","Version 3/9/2009\n";
}
Code to vdpau-detector
Code :
#!/bin/bash
# This script written by nickca on the linhes forums
# Original page http://www.knoppmythwiki.org/index.php?page=HardwareAcceleratedVideo
#
# It's modded to allow vdpau switches commands to pass to a modded version of Bob Igo's
# mplayer-resumer.pl wrapper for mplayer
#
# User can customize commandline for mplayer by editing the appropriate sections below
# They include BASIC_OPTS, NOHD_OPTS, and LOW_OPTS
IAM=$0
FILE=$1
#if no input display usage
if [[ -z "$FILE" ]]; then
echo usage: $0 /path/to/file
exit
fi
MPLAYER="/usr/bin/mplayer"
# For a complete list of options, see the mplayer DOCS
# http://www.mplayerhq.hu/DOCS/man/en/mplayer.1.html
#
# Options for all videos: fullscreen, zoom, and use software eq
BASIC_OPTS="-fs -zoom"
# Options for non-HD videos: force aspect to 16x10 (to ensure video fills TV screen)
# You'll need to modify the ratio if your res differs
# Example: 1920x1080 = 1.778 = 16:9
# Example: 1680x1050 = 1.600 = 16:10
# Example: 1280x720 = 1.778 = 16:9
NOHD_OPTS="-aspect 16:10"
# Options for normal and lowres videos: use XV forcing 16x10
LOW_OPTS="-aspect 16:10 -vo xv"
VWIDTH=$($MPLAYER -identify -vo vdpau -frames 0 "$FILE" | grep ID_VIDEO_WIDTH | cut -c 16-25)
VCODEC=$($MPLAYER -identify -vo vdpau -frames 0 "$FILE" | grep ID_VIDEO_CODEC | cut -c 16-25)
# all following echo commands can be uncommented for debug info
#echo .
#echo " DEBUG info: video codec: $VCODEC"
#echo " DEBUG info: video width: $VWIDTH"
#echo " Debug info:
# Test for codec, if it's supported by VDPAU, set options to use it. Then, check if the video is in HD,
# and if it's not, set non-HD options.
case $VCODEC in
ffh264)
#echo -e "Playing h.264 file $FILE:\n"
MPLAYEROPTS="$BASIC_OPTS -vo vdpau -vc ffh264vdpau"
if [ $VWIDTH -lt 1280 ] && [ $VWIDTH != 0 ]; then
MPLAYEROPTS="$MPLAYEROPTS $NOHD_OPTS"
fi
if [ $VWIDTH -lt 700 ] && [ $VWIDTH != 0 ]; then
MPLAYEROPTS="$BASIC_OPTS $LOW_OPTS"
fi
;;
ffmpeg2)
#echo -e "Playing MPEG2 file $FILE:\n"
MPLAYEROPTS="$BASIC_OPTS -vo vdpau -vc ffmpeg12vdpau"
if [ $VWIDTH -lt 1280 ] && [ $VWIDTH != 0 ]; then
MPLAYEROPTS="$MPLAYEROPTS $NOHD_OPTS"
fi
if [ $VWIDTH -lt 700 ] && [ $VWIDTH != 0 ]; then
MPLAYEROPTS="$BASIC_OPTS $LOW_OPTS"
fi
;;
ffwmv3)
#echo -e "Playing WMV3 file $FILE:\n"
MPLAYEROPTS="$BASIC_OPTS -vo vdpau -vc ffwmv3vdpau"
if [ $VWIDTH -lt 1280 ] && [ $VWIDTH != 0 ]; then
MPLAYEROPTS="$MPLAYEROPTS $NOHD_OPTS"
fi
if [ $VWIDTH -lt 700 ] && [ $VWIDTH != 0 ]; then
MPLAYEROPTS="$BASIC_OPTS $LOW_OPTS"
fi
;;
# VC-1 is largely unsupported by nvidia - uncomment this section if you're sure your card supports it.
ffvc1)
#echo -e "Playing VC-1 file $FILE:\n"
MPLAYEROPTS="$BASIC_OPTS -vo vdpau -vc ffvc1vdpau"
if [ $VWIDTH -lt 1280 ] && [ $VWIDTH != 0 ]; then
MPLAYEROPTS="$MPLAYEROPTS $NOHD_OPTS"
fi
if [ $VWIDTH -lt 700 ] && [ $VWIDTH != 0 ]; then
MPLAYEROPTS="$BASIC_OPTS $LOW_OPTS"
fi
;;
*)
#echo -e "Playing normal file $FILE:\n"
# Use XV and yadif filter with 'normal' (DiVX, XViD, old WMV, etc.) files, and force 16:9
# -vf filters only seem to work with XV, or at least they don't work w/VDPAU
MPLAYEROPTS="$BASIC_OPTS $LOW_OPTS"
;;
esac
echo $MPLAYEROPTS
10 More Discussions You Might Find Interesting
1. Shell Programming and Scripting
hi,
I would like to know of a shell script to create the following
A script which will take in two parameters i.e. name of file and SID and create directories named /opt/oracle/admin/$SID/{bdump,cdump,udump}. Then edit the init file and change the three lines that look like this.
... (2 Replies)
Discussion started by: sjajimi
2 Replies
2. Shell Programming and Scripting
I have a directory which is /home/mark/files/ , inside this particular I have a bunch of filles (see examples below)
TST_SHU_00014460_20090302.txt
TST_SHU_00016047_20090302.txt
TST_SHU_00007838_20090303.txt
TST_SHU_00056485_20090303.txt
TST_SHU_00014460_20090303.txt... (2 Replies)
Discussion started by: fierusbentus
2 Replies
3. Shell Programming and Scripting
Hi All,
I have a file with the following contents with multiple lines
172445957| 000005911|8| 400 Peninsula Ave.#1551 | And,K |935172445957|000005911
607573888 |000098536 | 2|Ane, B |J |Ane |1868 |19861206|20090106|20071001
I want to trim the "leading and trailing spaces only" from... (2 Replies)
Discussion started by: kumar04
2 Replies
4. UNIX for Advanced & Expert Users
Hi there,
I need to change all files/dirs
1. all files with 744
2. all dirs with 755
is there a script for that ?
thanks,
thegunman (13 Replies)
Discussion started by: TheGunMan
13 Replies
5. Shell Programming and Scripting
Hello,
Recently, I've started with shell scripting, and decided to write a script for my system backup using tar. When I was dealing with tar execution inside shell script I found this, inside shell we have the following code:
tar $TAR_PARAMS $ARCHIVE_FILE $EXCLUDE $BACKUP_STARTwith... (6 Replies)
Discussion started by: ilnar
6 Replies
6. UNIX for Dummies Questions & Answers
I am trying to get a listing of ALL directories only under /export (as an example). I can get all the dirs directly under /export but I need any sub dirs under those dirs. I've looked (here and google) but can not find anything that works (4 Replies)
Discussion started by: bbraml
4 Replies
7. Shell Programming and Scripting
I have a variable
I want to remove the spaces in between.
The output should be
How can this be done
Any help will be appreciated. Thanks in advance (1 Reply)
Discussion started by: irudayaraj
1 Replies
8. Shell Programming and Scripting
Example data
The sub and array in question
sub parse_status {
my $status_info = shift;
my @info;
push @info,"$1\n" if $status_info =~ /(System State : +)/;
push @info, "System_Uptime : $1\n" if $status_info =~ /Uptime:.+?up (.+?), load/;
push @info, "$1\n" if $status_info =~... (2 Replies)
Discussion started by: popeye
2 Replies
9. Shell Programming and Scripting
The following command to replace text in place in multiple files in a directory is tripping up on filename spaces (Windows environment). I really don't know Perl.
find '\\server\directory' | xargs perl -pi -e 's/textA/textB/g'Mike (2 Replies)
Discussion started by: Michael Stora
2 Replies
10. Shell Programming and Scripting
I would like to iterate over `dirs`in a script, but the script will never show more than one (current) folder
#! /bin/bash
for i in `dirs`
do
echo ${i}
done
echo ++++++++++++++++++
for i in $( dirs -p )
do
echo ${i}
done
echo ------------------
dirscontent=`dirs`
echo... (5 Replies)
Discussion started by: alexanderb
5 Replies