當我使用FLV::Info
模塊從多個FLV文件提取元數據或合併多個FLV文件時,我經常收到「Tag size is too small」錯誤,然後模塊將拒絕工作。有人在三年前發佈了一個錯誤報告here,但似乎沒有修復。我可以在Perl中更改加載模塊中的代碼行嗎?
好了,最近我發現,如果我只是註釋掉的代碼Tag.pm的FLV::Info
的依賴模塊之一以下行,像這樣:
=pod
if ($datasize < 11)
{
die "Tag size is too small ($datasize) at byte " . $file->get_pos(-10);
}
=cut
FLV::Info
便會很容易做的工作如預期。
我不知道如果這是一個非常愚蠢的問題,但我覺得好奇:
有沒有改變幾行代碼的加載模塊在不修改原有的.pm文件的一個簡單的方法?
任何意見,建議或意見? 感謝像往常一樣:)
UPDATE
非常感謝@Shwern。您的回答非常令人滿意:)還要感謝@DVK提供的建議,以及「猴子補丁」一詞和@brian的書籍推薦。
這是我對FLV文件示例的測試反饋,如果我使用原始模塊而不做任何事情,會導致「標記大小太小」錯誤。
的 「EVAL回來」 的方式解決了這個問題
use FLV::Info;
use Data::Dump::Streamer;
my $original = FLV::Tag->can("parse");
my $code = Dump($original)->Out;
#$code =~ s{\Qif ($datasize < 11)\E}{if (0)}; #This somehow won't work
$code =~ s{die "Tag}{warn "Tag}; #Let it warn but not die
no warnings 'redefine';
*FLV::Tag::parse = eval $code;
my $reader = FLV::Info->new();
$reader->parse('sample.flv');
my %info = $reader->get_info();
print "$info{video_count} video frames\n";
print $reader->report();
的 「超越控制芯片來沒有死」 的做法也適用
BEGIN {
*CORE::GLOBAL::die = sub { return CORE::die(@_) };
}
use FLV::Info;
{
local *CORE::GLOBAL::die = sub {
return if $_[0] =~ /^Tag size is too small/;
return CORE::die(@_);
};
my $reader = FLV::Info->new();
$reader->parse('sample.flv');
my %info = $reader->get_info();
print "$info{video_count} video frames\n";
print $reader->report();
}
的 「重新定義」 的方式,然而,不符合我的預期。
我複製和粘貼原來的FLV ::標籤::解析子程序和註釋掉的代碼行完全相同的方式我修改了原有的Tag.pm文件像這樣:
use FLV::Info;
no warnings 'redefine';
*FLV::Tag::parse = sub {
...
...
=pod
if ($datasize < 11)
{
die "Tag size is too small ($datasize) at byte " . $file->get_pos(-10);
}
=cut
...
...
};
my $reader = FLV::Info->new();
$reader->parse('sample.flv');
my %info = $reader->get_info();
print "$info{video_count} video frames\n";
print $reader->report();
但我得到這個錯誤:
Unknown tag type 18 at byte 13 (0xd)
好吧,就算複製和粘貼一模一樣的解析子程序沒有在我重新定義任何修飾,我收到「未知標籤類型」的錯誤,而不是「標籤尺寸太小」。
這很奇怪!
作爲參考,「EVAL回來」和「控死沒死」的方法給我以下內容:
1992 video frames
File name sample.flv
File size 5767831 bytes
Duration about 79.6 seconds
Video 1992 frames
codec AVC
type interframe/keyframe
Audio 1712 packets
format AAC
rate 44100 Hz
size 16 bit
type stereo
Meta 1 event
audiocodecid 10
audiosamplerate 22050
audiosamplesize 16
audiosize 342817
creationdate unknown
datasize 805
duration 79.6
filesize 5767869
framerate 25
height 300
keyframes {
>>> 'filepositions' => [
>>> '780',
>>> '865',
>>> '1324122',
>>> '2348913',
>>> '2978630',
>>> '3479001',
>>> '3973756',
>>> '4476281',
>>> '4997226',
>>> '5391890'
>>> ],
>>> 'times' => [
>>> '0',
>>> '0',
>>> '9.6',
>>> '19.2',
>>> '28.8',
>>> '38.4',
>>> '46.32',
>>> '55.92',
>>> '64.88',
>>> '73.88'
>>> ]
>>> }
lastkeyframetimestamp 73.88
lasttimestamp 79.6
metadatacreator Manitu Group FLV MetaData Injector 2
metadatadate 1281964633858
stereo 1
videocodecid 7
videosize 5424234
width 400
最後更新
我已經想通了,爲什麼通過打開嚴格和警告編譯指示,「重新定義」方法失敗。感謝@Schwern提醒:)
首先添加以下代碼行(從FLV :: Util模塊複製),然後重新定義FLV :: Tag :: parse子例程。
Readonly::Hash our %TAG_CLASSES => (
8 => 'FLV::AudioTag',
9 => 'FLV::VideoTag',
18 => 'FLV::MetaTag',
);
我在_Mastering Perl_中深入介紹了這些東西。 – 2010-09-06 18:36:40