Невозможно рекомбинировать фрагментированную загрузку данных MP3
Я использую Perl с WWW::Mechanize
загрузить файл MP3, который подается кусками по 400 КБ (около 20 секунд).
Когда я сохраняю данные с binmode
на дескрипторе файла, добавляя каждый блок по мере его поступления, правильно воспроизводится только первый блок; остальное нет.
Когда я не пользуюсь binmode
Я не могу воспроизвести весь файл - он играет, но звучит интересно!
Это моя программа
use WWW::Mechanize;
$agent = WWW::Mechanize->new( cookie_jar => {} );
@links = ("http://thehost.com/chunk1","http://thehost.com/chunk2","http://thehost.com/chunk3");
foreach (@links){
$agent->get($_);
my $filename = 'test.mp3';
open(my $fh, '>>', $filename) or die "Could not open file '$filename' $!";
binmode $fh;
print $fh $agent->content;
close $fh;
}
Что я делаю неправильно?
Обновить
Это заголовки HTTP, которые возвращаются.
Cache-Control: public
Connection: close
Date: Tue, 28 Oct 2014 18:38:37 GMT
Pragma:
Server: Apache
Content-Length: 409600
Content-Type: application/octet-stream
Expires: Sat, 24 Oct 2015 12:08:00 GMT
Access-Control-Allow-Origin: *
Client-Date: Tue, 28 Oct 2014 18:38:28 GMT
Client-Peer: **.**.***.***:80
Client-Response-Num: 1
3 ответа
Я сомневаюсь, что один файл mp3 просто разделяется после некоторого количества байтов, а затем эти куски предлагаются в качестве отдельных загрузок. Вместо этого я предполагаю, что это каждый отдельный mp3-файл, который содержит 20 секунд исходного файла, и каждый из URL содержит правильный mp3-файл. Поскольку mp3 - это не данные, а заголовок и данные, вы не можете просто объединить эти mp3-файлы, просто соединив их вместе. Вместо этого вы должны использовать такую программу, как ffmpeg, для создания одного mp3-файла из нескольких mp3-файлов, см. https://superuser.com/questions/314239/how-to-join-merge-many-mp3-files
Я подозреваю, что контент подается с неправильными заголовками, и, поскольку вы используете API, который автоматически декодирует, это повреждает поток октетов.
Использовать mirror
метод вместо этого и объединить файлы после загрузки.
Я не могу объяснить поведение, которое вы получаете, но WWW::Mechanize
предназначен для работы с текстовыми страницами HTML, и не так хорош с двоичными данными. С использованием LWP::UserAgent
Модуль напрямую совсем не сложен.
Я предлагаю вам использовать что-то вроде этого вместо этого.
use strict;
use warnings;
use 5.010;
use autodie;
use LWP;
my @links = qw(
http://thehost.com/chunk1
http://thehost.com/chunk2
http://thehost.com/chunk3
);
my $agent = LWP::UserAgent->new;
my $filename = 'test.mp3';
open my $fh, '>:raw', $filename;
for my $link (@links) {
my $resp = $agent->get($link);
die $resp->status_line unless $resp->is_success;
print $fh $resp->decoded_content;
}
close $fh;
Если у вас все еще есть проблемы, пожалуйста, добавьте такую строку
print $resp->headers_as_string, "\n\n";
сразу после get
позвоните и сообщите о результатах, которые вы получите.
Вы также можете получить некоторые результаты, используя content
метод вместо decoded_content
,
Конечно, это может сильно нам помочь , если вы сможете выдавать реальные URL-адреса, но я понимаю, что вы не сможете этого сделать.