Skip Menu |

This queue is for tickets about the FFprobe CPAN distribution.

Report information
The Basics
Id: 73803
Status: open
Priority: 0/
Queue: FFprobe

People
Owner: Nobody in particular
Requestors: jason.froebe [...] gmail.com
Cc:
AdminCc:

Bug Information
Severity: Wishlist
Broken in: v0.0.3
Fixed in: (no value)



Subject: Not all stream data is covered in the ffprobe formatted output (some is in stderr)
I have multiple audiobook files (m4b) that ffprobe is able to retrieve the chapters from just fine... except the chapter information is printed to stderr and never in the formatted (STDOUT) output. Feature request is to format the chapter output. jason@jason-Inspiron-1545 ~/bin $ ffprobe "/home/jason/Audiobooks/Ben Bova/Mars/Mars 1.m4b" 1>/dev/null ffprobe version 0.7.2-4:0.7.2-1ubuntu1, Copyright (c) 2007-2011 the Libav developers built on Oct 2 2011 15:13:26 with gcc 4.6.1 configuration: --extra-version='4:0.7.2-1ubuntu1' --arch=amd64 --prefix=/usr --enable-vdpau --enable-bzlib --enable-libgsm --enable-libschroedinger --enable-libspeex --enable-libtheora --enable-libvorbis --enable-pthreads --enable-zlib --enable-libvpx --enable-runtime-cpudetect --enable-vaapi --enable-gpl --enable-postproc --enable-swscale --enable-x11grab --enable-libdc1394 --enable-shared --disable-static WARNING: library configuration mismatch avutil configuration: --extra-version='4:0.7.2.1ubuntu1+medibuntu1' --arch=amd64 --prefix=/usr --enable-vdpau --enable-bzlib --enable-libgsm --enable-libschroedinger --enable-libspeex --enable-libtheora --enable-libvorbis --enable-pthreads --enable-zlib --enable-libvpx --enable-runtime-cpudetect --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-version3 --enable-vaapi --enable-libopenjpeg --enable-libfaac --enable-nonfree --enable-gpl --enable-postproc --enable-swscale --enable-x11grab --enable-libdirac --enable-libmp3lame --enable-librtmp --enable-libx264 --enable-libxvid --enable-libopencore-amrnb --enable-version3 --enable-libopencore-amrwb --enable-version3 --enable-libvo-aacenc --enable-version3 --enable-libvo-amrwbenc --enable-version3 --enable-libdc1394 --enable-shared --disable-static avcodec configuration: --extra-version='4:0.7.2.1ubuntu1+medibuntu1' --arch=amd64 --prefix=/usr --enable-vdpau --enable-bzlib --enable-libgsm --enable-libschroedinger --enable-libspeex --enable-libtheora --enable-libvorbis --enable-pthreads --enable-zlib --enable-libvpx --enable-runtime-cpudetect --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-version3 --enable-vaapi --enable-libopenjpeg --enable-libfaac --enable-nonfree --enable-gpl --enable-postproc --enable-swscale --enable-x11grab --enable-libdirac --enable-libmp3lame --enable-librtmp --enable-libx264 --enable-libxvid --enable-libopencore-amrnb --enable-version3 --enable-libopencore-amrwb --enable-version3 --enable-libvo-aacenc --enable-version3 --enable-libvo-amrwbenc --enable-version3 --enable-libdc1394 --enable-shared --disable-static libavutil 51. 7. 0 / 51. 7. 0 libavcodec 53. 5. 0 / 53. 5. 0 libavformat 53. 2. 0 / 53. 2. 0 libavdevice 53. 0. 0 / 53. 0. 0 libavfilter 2. 4. 0 / 2. 4. 0 libswscale 2. 0. 0 / 2. 0. 0 libpostproc 52. 0. 0 / 52. 0. 0 [mov,mp4,m4a,3gp,3g2,mj2 @ 0x14acac0] max_analyze_duration reached Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/home/jason/Audiobooks/Ben Bova/Mars/Mars 1.m4b': Metadata: major_brand : M4B minor_version : 0 compatible_brands: M4B mp42isom creation_time : 2009-09-08 16:19:29 album : Mars artist : Ben Bova genre : Audiobook Duration: 03:51:23.41, start: 0.000000, bitrate: 81 kb/s Chapter #0.0: start 0.000000, end 2779.567914 Metadata: title : Mars - 01 of 24 Chapter #0.1: start 2779.567914, end 5555.049161 Metadata: title : Mars - 02 of 24 Chapter #0.2: start 5555.049161, end 8334.617075 Metadata: title : Mars - 03 of 24 Chapter #0.3: start 8334.617075, end 11110.098322 Metadata: title : Mars - 04 of 24 Chapter #0.4: start 11110.098322, end 13883.419864 Metadata: title : Mars - 05 of 24 Stream #0.0(und): Audio: aac, 44100 Hz, stereo, s16, 80 kb/s Metadata: creation_time : 2009-09-08 16:19:29 Stream #0.1(eng): Subtitle: text / 0x74786574 Metadata: creation_time : 2009-09-08 17:31:00 Unsupported codec with id 94213 for input stream 1 jason@jason-Inspiron-1545 ~/bin $
patch to add m4b chapter support: 82c82 < my ($tree, $branch, $tag, $stream); --- Show quoted text
> my ($tree, $branch, $tag, $stream, $chapter);
100c100,108 < } --- Show quoted text
> } elsif ($line =~ m/Chapter \#(\d+\.*\d+): start (\d+\.*\d+)\, end
(\d+\.*\d+)/i) { Show quoted text
> my ($start, $end) = ($2, $3); > $chapter = $1; > $chapter =~ s/\.//g; > $chapter =~ s/^0+(\d)/$1/; > > $$tree{chapters}{$chapter} = { start => $start, end => $end }; > } elsif ($line =~ /title\s+: (.+)$/) { > $$tree{chapters}{$chapter}{title} = $1;
101a110 Show quoted text
> }
So the output would be: jason@jason-Inspiron-1545 ~/bin $ ./test_mp4_info.pl -i "/home/jason/Audiobooks/Ben Bova/Mars/Mars 1.m4b" $VAR1 = { 'format' => { 'TAG:genre' => 'Audiobook', 'format_long_name' => 'QuickTime/MPEG-4/Motion JPEG 2000 format', 'format_name' => 'mov,mp4,m4a,3gp,3g2,mj2', 'TAG:creation_time' => '2009-09-08 16:19:29', 'TAG:major_brand' => 'M4B', 'start_time' => '0.000000', 'nb_streams' => '2', 'TAG:compatible_brands' => 'M4B mp42isom', 'duration' => '13883.419864', 'TAG:album' => 'Mars', 'size' => '141602866.000000', 'bit_rate' => '81595.000000', 'filename' => '/home/jason/Audiobooks/Ben Bova/Mars/Mars 1.m4b', 'TAG:minor_version' => '0', 'TAG:artist' => 'Ben Bova' }, 'stream' => [ { 'TAG:language' => 'und', 'bits_per_sample' => '0', 'codec_tag_string' => 'mp4a', 'TAG:creation_time' => '2009-09-08 16:19:29', 'codec_tag' => '0x6134706d', 'avg_frame_rate' => '11025/256', 'nb_frames' => '597909', 'time_base' => '1/44100', 'codec_time_base' => '0/1', 'sample_rate' => '44100.000000', 'channels' => '2', 'codec_type' => 'audio', 'codec_long_name' => 'Advanced Audio Coding', 'start_time' => '0.000000', 'duration' => '13883.419864', 'index' => '0', 'codec_name' => 'aac', 'r_frame_rate' => '0/0' }, { 'TAG:language' => 'eng', 'codec_tag_string' => 'text', 'TAG:creation_time' => '2009-09-08 17:31:00', 'codec_type' => 'subtitle', 'start_time' => '0.000000', 'duration' => '13883.419864', 'codec_tag' => '0x74786574', 'index' => '1', 'avg_frame_rate' => '0/0', 'codec_name' => 'unknown', 'r_frame_rate' => '0/0', 'nb_frames' => '5', 'codec_time_base' => '1/44100', 'time_base' => '1/44100' } ], 'chapters' => { '4' => { 'title' => 'Mars - 05 of 24', 'end' => '13883.419864', 'start' => '11110.098322' }, '1' => { 'title' => 'Mars - 02 of 24', 'end' => '5555.049161', 'start' => '2779.567914' }, '3' => { 'title' => 'Mars - 04 of 24', 'end' => '11110.098322', 'start' => '8334.617075' }, '0' => { 'title' => 'Mars - 01 of 24', 'end' => '2779.567914', 'start' => '0.000000' }, '2' => { 'title' => 'Mars - 03 of 24', 'end' => '8334.617075', 'start' => '5555.049161' } } }; The start/end is in seconds :) jason
Subject: FFprobe.pm
package FFprobe; use common::sense; use Carp; use Encode; use version 0.77; our $VERSION = qv("v0.0.3"); =head1 NAME FFprobe - probes information from multimedia files using C<ffprobe> =head1 PREREQUISITES This module requires that the C<ffprobe> program is present and accessible through the PATH. It is part of the ffmpeg / libav suite. =cut qx{ffprobe -version 2>&1} =~ /libavcodec/ or croak "Could not execute 'ffprobe -version', ". "check whether it is installed and accessible through PATH"; =head1 SYNOPSIS use FFprobe; # may fail if ffprobe isn't present my $probe = FFprobe->probe_file("/path/to/multimedia/file"); print $probe->{format}->{format_name}; print $probe->{stream}->[0]->{codec_name}; =head1 METHODS =head2 C<probe_file($)> use FFprobe; my $probe = FFprobe->probe_file("/path/to/file"); Runs C<ffprobe -show_format -show_streams> on the filename given as argument. Returns a hashref with a structured form parsed from ffprobe's output. Sample output: $VAR1 = { 'format' => { 'start_time' => '0.000000', 'filename' => '/path/to/input/file', }, 'stream' => [ { 'index' => '0', 'codec_tag' => '0x0000', }, { 'index' => '1', 'codec_tag' => '0x0000', } ] }; The C<index> entry may not exist if there is only one stream. =cut sub __run_ffprobe(@) { if(open my $child, "-|") { return $child; } else { close STDERR; open STDERR, ">&STDOUT"; exec('ffprobe', '-show_format', '-show_streams', @_); exit(1); } } my $utf8 = find_encoding("UTF-8"); sub probe_file($$) { my ($class, $file) = @_; my $probe = __run_ffprobe $file; my ($tree, $branch, $tag, $stream, $chapter); while(my $line = <$probe>) { $line = $utf8->decode($line); if($line =~ m!^\[(/?)(STREAM|FORMAT)\]!) { if ($1 eq "/") { $branch = undef; } else { $tag = lc($2); $branch = ($$tree{$tag} //= {}); $stream = $branch; } } elsif (defined $branch and $line =~ /^(.*?)=(.*)$/) { if ($1 eq "index") { $branch = ($$tree{$tag} = []) unless ref $branch eq 'ARRAY'; $stream = ($$branch[$2] //= {}); } $$stream{$1} = $2; $$stream{$1} =~ s/\s+$//s; } elsif ($line =~ m/Chapter \#(\d+\.*\d+): start (\d+\.*\d+)\, end (\d+\.*\d+)/i) { my ($start, $end) = ($2, $3); $chapter = $1; $chapter =~ s/\.//g; $chapter =~ s/^0+(\d)/$1/; $$tree{chapters}{$chapter} = { start => $start, end => $end }; } elsif ($line =~ /title\s+: (.+)$/) { $$tree{chapters}{$chapter}{title} = $1; } } close $probe; return $tree; } =head1 AUTHOR Diogo Franco (Kovensky) C<< <diogomfranco at gmail.com> >> =head1 LICENSE AND COPYRIGHT Copyright 2011 Diogo Franco. This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License. See http://dev.perl.org/licenses/ for more information. =cut 1;
Subject: test_mp4_info.pl
#!/usr/bin/perl use strict; use warnings; use lib qw(/home/jason/bin); use Getopt::Std; use FFprobe; my %arg_options = (); getopts('i:', \%arg_options); if ($arg_options{i}) { my $input_file = $arg_options{i}; my $mp4 = FFprobe->probe_file($input_file); use Data::Dumper; print Dumper($mp4); }