LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Software
User Name
Password
Linux - Software This forum is for Software issues.
Having a problem installing a new program? Want to know which application is best for the job? Post your question in this forum.

Notices


Reply
  Search this Thread
Old 06-21-2004, 08:42 AM   #1
mbabuskov
Member
 
Registered: Nov 2003
Location: Subotica
Distribution: Slackware, Knoppix, Mandriva
Posts: 42

Rep: Reputation: 15
Getting movie length from shell


Hi all,

I made a simple script that uses "du" to show me how much each divx movie I have takes space on disk. Now, I'd like to add feature to show movie length besides the file size.

I know that many (all?) movie players like mplayer, xine, etc. know this data, but I haven't found a way to retrieve it from them.

It would be great if I could just do:
mplayer --get-length movie.avi

And it just outputs:
01:32:55

TIA
 
Old 06-21-2004, 06:25 PM   #2
acid_kewpie
Moderator
 
Registered: Jun 2001
Location: UK
Distribution: Gentoo, RHEL, Fedora, Centos
Posts: 43,417

Rep: Reputation: 1981Reputation: 1981Reputation: 1981Reputation: 1981Reputation: 1981Reputation: 1981Reputation: 1981Reputation: 1981Reputation: 1981Reputation: 1981Reputation: 1981
what kind of files are you doing? if you're just looking at simple avi files all the time then it's actually very very very simple.

Code:
chris@kermit chris $ ./aviinfo /var/film/futurama/futurama-1-01-space_pilot_3000.avi 
ms per frame: 50000
total frames: 26186
width: 352
height: 240
chris@kermit chris $ cat aviinfo 
#!/usr/bin/perl
use strict;

open (AVI, $ARGV[0]);

my $data = "";
my $i;

# find hdrl
for (1..200) {
  read AVI, $data, 4;
  last if $data eq "hdrl"
}

#while ($data ne "hdrl")
#{ read AVI, $data, 4 }

# find avih
read AVI, $data, 4;

# waste 4
read AVI, $data, 4;

# ms per frame
read AVI, $data, 4;
print"ms per frame: " . converttoint($data). "\n";

# waste 12
read AVI, $data, 12;

# total frames
read AVI, $data, 4;
print"total frames: " . converttoint($data). "\n";

# waste 12
read AVI, $data, 12;

# width
read AVI, $data, 4;
print "width: " . converttoint($data) . "\n";

# height
read AVI, $data, 4;
print "height: " . converttoint($data) . "\n";

sub converttoint {
  my $total=0;
  for ($i = 0; $i < length($data); $i++) {
    my $c = substr($data, $i, 1);
    my $value = 256**$i * ord($c);
    $total += $value;
  }
  return $total;
}
don't worry if you're not used to perl... you'll do fine to just hack out the bits you don't want and reformat the results etc... you can do it!

it's easy to get a similar result from mplayer, using the -identify option, but this is much slower, and will still require parsing and processing anyway.
 
Old 06-21-2004, 07:25 PM   #3
wapcaplet
LQ Guru
 
Registered: Feb 2003
Location: Colorado Springs, CO
Distribution: Gentoo
Posts: 2,018

Rep: Reputation: 48
There is also tcprobe, part of the transcode package, that can (usually) tell you the running time of most videos. 'tcprobe -i filename'

Extracting the relevant information, though, would require additional scripting stuff with perl or whatnot. If you plan to re-use the information inside a script, you'll probably need to do something like acid_kewpie's script does.

You're right, it'd be great if there was a simple little utility to spit out that kind of info. I have some scripts that need to know frame rate, resolution, etc. Maybe if no such thing exists, I should work on writing one...

edit: Looks like 'mplayer -identify' produces the best starting place for such output (thanks acid_kewpie!), especially when run from the 'midentify' script (mine's in /usr/share/doc/mplayer-1.0_pre4/TOOLS) that suppresses other output. Here's a little script (complete hack, but gets the job done)

Code:
#!/bin/bash
LEN=`mplayer -vo null -ao null -frames 0 -identify "$@" 2>/dev/null | \
  grep "^ID_LENGTH" | sed -e 's/ID_LENGTH=//g'`
HR=$(($LEN / 3600))
MIN=$(( $(($LEN - $HR * 3600)) / 60 ))
SEC=$(($LEN % 60))
echo "$HR:$MIN:$SEC"

Last edited by wapcaplet; 06-21-2004 at 07:42 PM.
 
Old 06-22-2004, 01:35 AM   #4
mbabuskov
Member
 
Registered: Nov 2003
Location: Subotica
Distribution: Slackware, Knoppix, Mandriva
Posts: 42

Original Poster
Rep: Reputation: 15
This is just great

Thanx for the quick replies, all works now.

Bye,
Milan
 
Old 06-22-2004, 02:52 PM   #5
mbabuskov
Member
 
Registered: Nov 2003
Location: Subotica
Distribution: Slackware, Knoppix, Mandriva
Posts: 42

Original Poster
Rep: Reputation: 15
Now I have run into the next problem.

I'm trying to get length for all movies in all subdirectories of current directory

I tried something like this:

for i in `find -iname *.avi`; do echo $i `size.sh $i`; done

and it works if files and dirs don't have space in their names. But if they do, it falls apart.

I tried some variations with awk and sed, but couldn't get it to work.
Any ideas?



P.S. size.sh contains the script wapcaplet wrote.
 
Old 06-22-2004, 03:03 PM   #6
wapcaplet
LQ Guru
 
Registered: Feb 2003
Location: Colorado Springs, CO
Distribution: Gentoo
Posts: 2,018

Rep: Reputation: 48
Just guessing here, but try putting double-quotes around the $i variable.
 
Old 06-22-2004, 03:48 PM   #7
mbabuskov
Member
 
Registered: Nov 2003
Location: Subotica
Distribution: Slackware, Knoppix, Mandriva
Posts: 42

Original Poster
Rep: Reputation: 15
Quote:
Originally posted by wapcaplet
Just guessing here, but try putting double-quotes around the $i variable.
Doesn't work.

The problem is that for/find combination sets $i wrong. For example if I have

./cd 1/movie1.avi
./cd 2/movie2.avi

Running for/find, gives $i the following 4 values:
./cd
1/movie1.avi
./cd
2/movie2.avi

Placing it in the quotes doesn't change anything.

Any other idea?
 
Old 06-22-2004, 11:00 PM   #8
wapcaplet
LQ Guru
 
Registered: Feb 2003
Location: Colorado Springs, CO
Distribution: Gentoo
Posts: 2,018

Rep: Reputation: 48
Perhaps instead of the for-loop construct, you could use the -exec option of 'find' to execute the script for each result. Not sure of the exact syntax, but try:

Code:
find . -iname '*.avi' -exec size.sh '{}' ';'
That should run size.sh, passing each result of 'find' to it in turn. Not sure how to get it to print out each one as it does them, but I guess you could make that part of size.sh. Maybe this:

Code:
find . -iname '*.avi' -exec echo '{}' && size.sh '{}' ';'
 
Old 06-23-2004, 06:49 PM   #9
mbabuskov
Member
 
Registered: Nov 2003
Location: Subotica
Distribution: Slackware, Knoppix, Mandriva
Posts: 42

Original Poster
Rep: Reputation: 15
Quote:
Originally posted by wapcaplet
Perhaps instead of the for-loop construct, you could use the -exec option of 'find' to execute the script for each result. Not sure of the exact syntax, but try:

Code:
find . -iname '*.avi' -exec size.sh '{}' ';'
Excellent.

That's exactly what I needed. I did try something with -exec but didn't know that I had to use {}

I have altered size.sh to output exactly what I want, so now I got the complete script that parses my entire movie database and prints movie names with sizes in MB and length. It also groups them by partitions and writes subtotals and total (in GB). (If anyone needs it, I can post it here)

Thank you very much for your help.

Regards,
Milan.
 
Old 06-23-2004, 10:45 PM   #10
wapcaplet
LQ Guru
 
Registered: Feb 2003
Location: Colorado Springs, CO
Distribution: Gentoo
Posts: 2,018

Rep: Reputation: 48
Quote:
Originally posted by mbabuskov
That's exactly what I needed. I did try something with -exec but didn't know that I had to use {}
Yeah, I always have to look up the syntax for that, since it's sort of unintuitive. The Linux Cookbook has a lot of good examples.
 
Old 03-12-2012, 07:33 AM   #11
dare2be
LQ Newbie
 
Registered: Mar 2012
Posts: 1

Rep: Reputation: Disabled
Update of the script

I know this thread is old, but for sake of future copy-n-paste Googlers, here's an updated version of the midentify script:

Code:
#!/bin/bash
LEN=$(mplayer -vo null -ao null -frames 0 -identify "$@" 2>/dev/null | \
  grep "^ID_LENGTH" | sed -e 's/ID_LENGTH=//g')
HR=$(echo "$LEN/3600"|bc)
MIN=$(echo "($LEN-$HR*3600)/60"|bc)
SEC=$(echo "$LEN%60"|bc)
echo $(printf "%02.0f:%02.0f:%02.0f" $HR $MIN $SEC)
The old version would sometimes break with the following error:
Code:
/usr/local/bin/midentify: line 4: 1324.00 / 3600: syntax error: invalid arithmetic operator (error token is ".00 / 3600")
/usr/local/bin/midentify: line 5: 1324.00 -  * 3600: syntax error: invalid arithmetic operator (error token is ".00 -  * 3600")
/usr/local/bin/midentify: line 6: 1324.00 % 60: syntax error: invalid arithmetic operator (error token is ".00 % 60")
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Password length ust Linux - Distributions 1 04-06-2005 06:18 AM
Shell scripting to find length of filenames ridertech Linux - Newbie 2 08-25-2004 01:07 PM
sound length mihman Linux - Software 0 08-21-2003 06:21 AM
Horizontal Length rch LQ Suggestions & Feedback 1 05-16-2003 04:21 AM
message length boku LQ Suggestions & Feedback 2 08-05-2002 12:57 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Software

All times are GMT -5. The time now is 12:21 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration