Невозможно рекомбинировать фрагментированную загрузку данных 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-адреса, но я понимаю, что вы не сможете этого сделать.

Другие вопросы по тегам