当我使用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