Cuando uso el módulo FLV::Info
para extraer metadatos o combinar varios archivos FLV, recibo con frecuencia un error de "Tamaño de etiqueta demasiado pequeño" y luego el módulo simplemente se niega a trabajar. Alguien emitió un informe de error here hace tres años, pero no parece haber una solución.¿Puedo cambiar las líneas de código en un módulo cargado en Perl?
Bueno, hace poco me encuentro si simplemente comente las siguientes líneas de código en Tag.pm, uno de los módulos de dependencia FLV::Info
's de este modo:
=pod
if ($datasize < 11)
{
die "Tag size is too small ($datasize) at byte " . $file->get_pos(-10);
}
=cut
FLV::Info
continuación, va a hacer el trabajo fácilmente como se esperaba .
No estoy seguro si esto es una pregunta muy tonta, pero me siento curiosidad:
¿Hay una manera sencilla de cambiar un par de líneas de código en un módulo cargado sin modificar el archivo .pm original?
¿Alguna idea, sugerencia o comentario? Gracias como siempre :)
ACTUALIZACIÓN
Muchas gracias a @Shwern. Su respuesta es muy satisfactoria :) También gracias a @DVK por la sugerencia y el término "parche de mono" y @brian por la recomendación del libro.
Aquí está mi opinión sobre las pruebas en un archivo FLV de muestra que me arrojaría el error "El tamaño de la etiqueta es demasiado pequeño" si utilizo el módulo original sin hacer nada al respecto.
El enfoque "eval nuevo" resuelve el problema
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();
El "Die overide para no morir" enfoque también funciona
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();
}
El enfoque de "redefinir", sin embargo, no funciona como esperaba.
que copiar y pegar la etiqueta FLV originales :: :: subrutina de análisis y comentado las líneas de código exactamente la forma en que modifican el archivo Tag.pm original de este modo:
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();
pero tengo este error:
Unknown tag type 18 at byte 13 (0xd)
Bueno, incluso si copiar y pegar exactamente la misma subrutina de análisis sin ninguna modificación en mi nueva definición, que estoy recibiendo el error "Desconocido tipo de etiqueta" en lugar de "tamaño de la etiqueta es demasiado pequeña".
¡Esto es extraño!
Como referencia, el "eval de nuevo" y "anular morir para no morir" enfoques me darán los siguientes:
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
INFORME FINAL DE ACTUALIZACIÓN
que he descubierto por qué el el enfoque "redefinir" falló al activar el pragma estricto y las advertencias. Gracias a @Schwern para el recordatorio :)
Agregue las siguientes líneas de código (copiadas del módulo FLV :: Util) primero y luego realice la redefinición de la subrutina FLV :: Tag :: parse.
Readonly::Hash our %TAG_CLASSES => (
8 => 'FLV::AudioTag',
9 => 'FLV::VideoTag',
18 => 'FLV::MetaTag',
);
Cubro algunas de estas cosas en profundidad en _Mastering Perl_. –