Дима Яковлев

Скробблинг iPod на Last.fm на PHP

Apple и Last.fm совместными усилиями лишили пользователей плееров iPod возможности вести статистику прослушивания треков — скробблер Last.fm не устанавливается на устаревшие версии iOS, что актуально для iPod Touch; текущая версия iTunes не работает с десктопным скробблером Last.fm, поддерживающим скробблинг с iPod, что актуально для остальных версий iPod. Владельцу iPod в этой ситуации остаётся либо перестать пользоваться своим плеером и сменить его на другое устройство, либо отказаться от ведения статистики в Last.fm. Ни первый, ни второй варианты мне не подходят, поэтому пришлось придумать собственное решение для обхода созданных компаниями ограничений. Если проблема совместного использования iPod и Last.fm коснулась и вас, читайте дальше.

Для работы понадобится установленный iTunes и PHP. PHP был выбран из-за удобства и доступности на разных платформах, а iTunes нужен для управления музыкой на плеере и экспорта плейлистов. Не смотря на использование PHP, решение не имеет отношения к вебу, всё выполняется в консоли, без задействования веб-сервера и браузера.

Путь к успешному скробблингу состоит из двух последовательных шагов: подготовительного, для получения лога прослушиваний треков на плеере, и непосредственно скробблинга треков из лога.

Шаг 1. Получение лога прослушиваний

Эту задачу выполняет мой скрипт scrobblerlog.php. Работа со скриптом подробно описана на его странице. Загрузите актуальную копию скрипта из репозитория любым удобным способом.

После того как скрипт загружен, при помощи iTunes подготовлены эталонный и разностный плейлисты, в командной строке выполните команду:

php scrobblerlog.php -r=/path/to/reference/playlist -d=/path/to/difference/playlist -l=/path/to/log -o -t

Например, если плейлисты экспортированы в стандартную папку библиотеки iTunes в Windows, скрипт запускается в WSL, а лог сохраняется в корень файловой системы iPod, которому присвоена буква диска I, аргументы будут иметь следующие значения:

php scrobblerlog.php -r=/mnt/c/Users/Username/Music/iTunes/reference.txt -d=/mnt/c/Users/Username/Music/iTunes/difference.txt -l=/mnt/i/scrobbler.log -o -t

Если в консоль не были выведены сообщения об ошибках обработки плейлистов, что может быть при их ручной доработке после экспорта из iTunes, лог прослушиваний сохранён в файл /mnt/i/scrobbler.log. Для проверки корректности данных можно открыть его в текстовом редакторе или вывести в консоль.

cat /mnt/i/scrobbler.log

Я советую сделать это для того, чтобы понять формат данных, сохранённых в лог. Проверять корректность лога постоянно не требуется, scrobblerlog.php выполняет проверку входных данных из плейлистов и предотвращает связанные с ними возможные ошибки на выходе.

Полученный лог-файл используется в Шаге 2.

Шаг 2. Скробблинг треков из лога

Я решил не усложнять задачу и использовать уже готовый класс PHP-Scrobbler, написанный Ben XO. Поэтому загрузите или скопируйте код класса из репозитория автора. На всякий случай доступен мой форк.

Для скробблинга вам требуется иметь действующие логин и пароль пользователя Last.fm. Проверьте их, выполнив вход на сайте Last.fm. Если вход выполнен без ошибок, логин и пароль будут использоваться далее, если возникла ошибка, восстановите пароль.

Теперь непосредственно PHP-код, выполняющий разбор лог-файла и отправку информации о прослушанных треках сервису Last.fm. Как уже писал, код предназначен только для выполнения в консоли.

<?php

if (php_sapi_name() !== 'cli') {
    exit;
}

$user = 'username'; # last.fm user name
$pass = 'password'; # last.fm user password
$log = '/mnt/i/scrobbler.log'; # path to log file
$delay = true; # use delay between scrobbles

# use require or paste class md_Scrobbler code
require('Scrobbler.php');

$scrobbler = new md_Scrobbler($user, $pass);

$log = file($log, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);

if ($log === false) {
    throw new Exception("Failed to open log file");
}

$count = count($log);

echo "$count track(s) to scrobble...\n";

if ($count == 0) {
    exit(1);
}

$timeshift = 0;

foreach ($log as $key => $row) {
    $track = str_getcsv($row, "\t");
    # $track[0] - artist
    # $track[1] - album
    # $track[2] - name
    # $track[3] - number
    # $track[4] - duration
    # $track[5] - source
    # $track[6] - timestamp
    $timestamp = $track[6];
    if ($key > 0) {
        if ($log[$key] == $log[$key - 1]) {
            $timeshift = $timeshift + $track[4];
            $timestamp = $timestamp - $timeshift;
        } else {
            $timeshift = 0;
        }
    }
    $scrobbler->add($track[0], $track[2], $track[1], $track[4], $timestamp, $track[3], $track[5]);
    $scrobbler->submit();
    $i = $key + 1;
    echo "Track $i from $count \"$track[2]\" by \"$track[0]\" from \"$track[1]\" was scrobbled.\n";
    if ($timeshift > 0) {
        echo "Original timestamp was shifted by -$timeshift second(s).\n";
    }
    if ($delay && $count != $i) {
        $wait = rand(1, 3);
        echo "Waiting for $wait second(s) to scrobble next track...\n";
        sleep($wait);
    }
}

Сохраните PHP-код в файл, например, scrobblerlastfm.php и измените значения переменных:

Обратите внимание на переменную $delay. Она включает паузу от 1 до 3 секунд между скробблингом треков. На практике, как правило, это не нужно, скробблинг работает без принудительного использования задержек, поэтому для отключения паузы между скробблингом треков присвойте переменной значение false: $delay = false;.

Когда значения переменных заданы, запустите выполнение скрипта в командной строке:

php scrobblerlastfm.php

Во время работы скрипт выводит в консоль информацию о текущем состоянии скробблинга треков. Если в Шаге 1 лог был сформирован скриптом scrobblerlog.php без атрибута -t или --timeshift, метка времени, то есть время прослушивания, для повторяющихся треков, следующих в логе друг за другом, будет скорректирована автоматически. Корректировка выполняется путём сдвига метки времени назад на продолжительность трека относительно метки времени предыдущего трека. Без корректировки меток времени повторяющиеся треки не будут учтены сервисом Last.fm, статистика их прослушиваний будет потеряна.

Предложенное мною решение полностью выполняет свою задачу, но всё-такие имеет два неудобства:

  1. необходимость экспорта плэйлистов вручную из iTunes;
  2. неточность статистики из-за потери реального времени прослушивания для треков, проигранных более одного раза.

Если экспорт плэйлистов можно частично автоматизировать, например, при помощи PowerShell, то с неточностью статистики приходится смириться. Таковы издержки, связанные с использование морально устаревших, как считают компании, плееров iPod совместно с сервисом Last.fm в 2020 году.