Created
November 14, 2022 13:18
-
-
Save tsuchm/cf7a23d9567c2f5d142cb2d7b59345c7 to your computer and use it in GitHub Desktop.
Script to parse AVCHD playlist format
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl | |
=head1 OBJECT OF THIS SCRIPT | |
Panasonic 製デジタルビデオカメラが,SD カードに動画を格納する時,動画データのファイル名は連番になっている. | |
これを,日付(8桁)-連番というファイル名に変更するために必要な情報を取り出す. | |
=head1 SYNOPSIS | |
perl playlist.pl PRIVATE/AVCHD/BDMV/PLAYLIST/00000.MPL | |
=cut | |
use Fcntl qw/ :seek /; | |
use Getopt::Long; | |
use strict; | |
use warnings; | |
use constant { VIDEONUM_POS => 65, | |
VIDEONUM_LEN => 1, | |
VIDEONAME_BEG => 70, | |
VIDEONAME_LEN => 5, | |
VIDEONAME_SIZE => 98, | |
HEADLEN_POS => 18, | |
HEADLEN_LEN => 2, | |
HEADLEN_OFFSET => 87 + 285 + 1, | |
VIDEODATE_LEN => 11, | |
VIDEODATE_SIZE => 66 }; | |
our $VERBOSE; | |
&GetOptions( 'verbose' => \$VERBOSE ); | |
sub main { | |
my( $file ) = @_; | |
printf STDERR "file=%s\n", $file if $VERBOSE; | |
open( my $fh, '<:raw', $file ) or die; | |
my $buf; | |
seek( $fh, VIDEONUM_POS, SEEK_SET ); | |
read( $fh, $buf, VIDEONUM_LEN ); | |
my( $num ) = unpack( 'C', $buf ); | |
printf STDERR "num=%d\n", $num if $VERBOSE; | |
my @name; | |
my $pos = VIDEONAME_BEG; | |
for( my $i = 0; $i < $num; $i++ ){ | |
printf STDERR "pos=%04X\n", $pos if $VERBOSE; | |
seek( $fh, $pos, SEEK_SET ); | |
read( $fh, $buf, VIDEONAME_LEN ); | |
my( $name ) = unpack( 'a*', $buf ); | |
printf STDERR "name=%s\n", $name if $VERBOSE; | |
push( @name, $name ); | |
$pos += VIDEONAME_SIZE; | |
} | |
seek( $fh, HEADLEN_POS, SEEK_SET ); | |
read( $fh, $buf, HEADLEN_LEN ); | |
$pos = unpack( 'n', $buf ); | |
printf STDERR "len=%d\n", $pos if $VERBOSE; | |
$pos += HEADLEN_OFFSET; | |
for( my $i = 0; $i < $num; $i++ ){ | |
printf STDERR "pos=%04X\n", $pos if $VERBOSE; | |
seek( $fh, $pos, SEEK_SET ); | |
read( $fh, $buf, VIDEODATE_LEN ); | |
my( $type, $date ) = unpack( 'Ca*', $buf ); | |
$pos += VIDEODATE_SIZE; | |
printf STDERR "type=%d\n", $type if $VERBOSE; | |
redo unless $type; | |
printf STDERR "date=%s\n", $date if $VERBOSE; | |
$date =~ s/ /0/g; | |
$date =~ s/\.//g; | |
printf "mv %s.MTS %s-%03d.MTS\n", $name[$i], $date, $i+1; | |
} | |
} | |
for my $f ( @ARGV ){ | |
&main( $f ); | |
} | |
=head1 DIRECTORY HIERACHY | |
Panasonic 製デジタルビデオカメラが,SD カードに動画を格納する時のディレクトリ構造の概要は,以下の通り. | |
PRIVATE/ | |
AVCHD/ | |
AVCHDTN/ | |
BDMV/ | |
INDEX.BDM | |
MOVIEOBJ.BDM | |
CLIPINF/ | |
PLAYLIST/ | |
00000.MPL | |
00001.MPL | |
00002.MPL | |
... | |
STREAM/ | |
00000.MTS | |
00001.MTS | |
00002.MTS | |
... | |
IISVPL/ | |
MPL という拡張子のファイルがプレイリストであり,MTS という拡張子のファイルが動画データである. | |
=head1 PLAYLIST FILE FORMAT | |
動画ファイルを2つ含む場合のプレイリストは,以下のようになっている. | |
00000000: 4d50 4c53 3031 3030 0000 003a 0000 0108 MPLS0100...:.... | |
00000010: 0000 0138 0000 0000 0000 0000 0000 0000 ...8............ | |
00000040: 0002 0000 0060 3030 3032 384d 3254 5300 .....`00028M2TS. | |
000000a0: 0590 6a70 6e00 0060 3030 3032 394d 3254 ..jpn..`00029M2T | |
00000180: 0000 0000 ffff 1e20 1505 2320 2840 0003 ....... ..# (@.. | |
00000190: 0a32 3030 392e 2036 2e32 3800 0000 0000 .2009. 6.28..... | |
000002a0: 0000 001c 1220 0906 2808 5203 030a 3230 ..... ..(.R...20 | |
000002b0: 3039 2e20 362e 3238 0000 0000 0000 0000 09. 6.28........ | |
000002e0: 0000 0000 001d 1220 0906 2809 2643 030a ....... ..(.&C.. | |
000002f0: 3230 3039 2e20 362e 3238 0000 0000 0000 2009. 6.28...... | |
ヘッダ領域: | |
0x0000(0): 「MPLS」ファイル種別ヘッダ | |
0x0004(4): 「0100」おそらく,MPLSフォーマットのバージョン番号 | |
0x000E(14): 0x0108(264) 動画ファイル名領域長(=68+98*ファイル数) | |
0x0012(18): 0x0138(312) ヘッダ領域長(この値に87を足すと,プレイリスト情報領域のアドレス) | |
0x0041(65): 0x02 動画リストに含まれる動画ファイル数 | |
動画ファイル名領域 #1(98バイト) | |
0x0045(69): 0x60 固定 | |
0x0046(70): 「00028」動画ファイル#1のファイル名(拡張子を含まず). | |
動画ファイル名領域 #2(98バイト) | |
0x00A7(167): 0x60 固定 | |
0x00A8(168): 「00029」動画ファイル#2のファイル名(拡張子を含まず). | |
??情報領域 | |
プレイリスト情報領域(285バイト) | |
0x018F(399): 0x030A 固定 | |
0x0191(401): 「2009. 6.28」おそらく,このプレイリストの作成日. | |
撮影日領域 #1(66バイト) | |
0x02AC(684): 0x03 固定 | |
0x02AD(685): 0x00 または 0x0A.0x00 の場合は,この領域をスキップ. | |
0x02AE(686): 「2009. 6.28」動画ファイルその1の撮影日. | |
撮影日領域 #2(66バイト) | |
0x02EE(750): 0x03 固定 | |
0x02EF(751): 0x00 または 0x0A.0x00 の場合は,この領域をスキップ. | |
0x02F0(752): 「2009. 6.28」動画ファイルその2の撮影日. | |
動画ファイルを3つ含む場合のプレイリストは,以下のようになっている. | |
00000000: 4d50 4c53 3031 3030 0000 003a 0000 016a MPLS0100...:...j | |
00000010: 0000 019a 0000 0000 0000 0000 0000 0000 ................ | |
00000040: 0003 0000 0060 3030 3032 354d 3254 5300 .....`00025M2TS. | |
000000a0: 0590 6a70 6e00 0060 3030 3032 364d 3254 ..jpn..`00026M2T | |
00000100: 0000 0590 6a70 6e00 0060 3030 3032 374d ....jpn..`00027M | |
000001f0: 0003 0a32 3030 392e 2036 2e32 3700 0000 ...2009. 6.27... | |
00000300: 0000 0000 0019 1220 0906 2709 0414 030a ....... ..'..... | |
00000310: 3230 3039 2e20 362e 3237 0000 0000 0000 2009. 6.27...... | |
00000350: 030a 3230 3039 2e20 362e 3237 0000 0000 ..2009. 6.27.... | |
00000390: 0550 030a 3230 3039 2e20 362e 3237 0000 .P..2009. 6.27.. | |
ヘッダ領域: | |
0x0000(0): 「MPLS」ファイル種別ヘッダ | |
0x0004(4): 「0100」おそらく,MPLSフォーマットのバージョン番号 | |
0x000E(14): 0x016A(362) 動画ファイル名領域長(=68+98*ファイル数) | |
0x0012(18): 0x019A(410) ヘッダ領域長(この値に87を足すと,プレイリスト情報領域のアドレス) | |
0x0041(65): 0x02 動画リストに含まれる動画ファイル数 | |
動画ファイル名領域 #1(98バイト) | |
0x0045(69): 0x60 固定 | |
0x0046(70): 「00025」動画ファイル#1のファイル名(拡張子を含まず). | |
動画ファイル名領域 #2(98バイト) | |
0x00A7(167): 0x60 固定 | |
0x00A8(168): 「00026」動画ファイル#2のファイル名(拡張子を含まず). | |
動画ファイル名領域 #3(98バイト) | |
0x0109(265): 0x60 固定 | |
0x010A(266): 「00027」動画ファイル#3のファイル名(拡張子を含まず). | |
プレイリスト情報領域(285バイト) | |
0x01F1(497): 0x030A 固定 | |
0x01F3(499): 「2009. 6.27」おそらく,このプレイリストの作成日. | |
撮影日領域 #1(66バイト) | |
0x030E(782): 0x03 固定 | |
0x030F(783): 0x00 または 0x0A.0x00 の場合は,この領域をスキップ. | |
0x0310(784): 「2009. 6.27」動画ファイルその1の撮影日. | |
撮影日領域 #2(66バイト) | |
0x0350(848): 0x03 固定 | |
0x0351(849): 0x00 または 0x0A.0x00 の場合は,この領域をスキップ. | |
0x0352(850): 「2009. 6.27」動画ファイルその2の撮影日. | |
撮影日領域 #3(66バイト) | |
0x0392(914): 0x030A 固定 | |
0x0393(915): 0x00 または 0x0A.0x00 の場合は,この領域をスキップ. | |
0x0394(916): 「2009. 6.27」動画ファイルその3の撮影日. | |
=head1 AUTHOR | |
TSUCHIYA Masatoshi <[email protected]> | |
=head1 COPYRIGHT | |
This program is free software: you can redistribute it and/or modify | |
it under the terms of the GNU General Public License as published by | |
the Free Software Foundation, either version 3 of the License, or | |
(at your option) any later version. | |
This program is distributed in the hope that it will be useful, | |
but WITHOUT ANY WARRANTY; without even the implied warranty of | |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
GNU General Public License for more details. | |
You should have received a copy of the GNU General Public License | |
along with this program. If not, see <http://www.gnu.org/licenses/>. | |
=cut |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment