Как это сделано?

Оглавление
1. Задача
2. С какими данными работаем
3. Какие технологии используются
4. Готовим данные к отображению на страницах
5. Выводим список имеющихся в директории выпусков
6. Делаем ссылки на аудио-плеер и текстовую расшифровку
7. Создаём страницу с аудио-плеером и текстовой расшифровкой
8. Что будет дальше?

В марте 2022-го года я опубликовал на этом сайте первую и, возможно, не последнюю порцию аудио-архивов радиостанции «Эхо Москвы». В начале апреля я наконец-то дописал скрипты, которые позволяют пользоваться этими архивами с относительным удобством. И сразу после этого я решил опубликовать, вот на этой самой странице, коды всех скриптов: вдруг кто-нибудь из читателей-разработчиков даст мне ценный совет по оптимизации? Или, наоборот, сочтёт этот низкотехнологический ужас полезным для каких-то своих целей?
Итак, пойдём по порядку.

1. Задача
Опубликовать архивы передач «Эха Москвы» и, в порядке приоритетности, сделать следующее:
— указать для каждого выпуска передачи тему, дату выхода в эфир, имена ведущих и продолжительность;
— дать возможность не только скачивать аудио-файлы, но и слушать их прямо на сайте;
— добавить возможность читать официальную текстовую расшифровку каждого выпуска передачи (в тех случаях, когда эта расшифровка существует в природе);
— опубликовать дополнительные материалы (или ссылки на них) к выпускам передач.

2. С какими данными работаем
Для каждого выпуска каждой передачи имеются файл *.mp3 со звуком (думаю, оригинальный формат всех устраивает) и файл *.txt с текстом расшифровки (этот формат мне кажется самым удобным для отображения на веб-страницах; почему текст не вставляется прямо в код страницы — поймёте по ходу рассказа). Пара файлов для каждого выпуска передачи имеет одинаковые имена (например, netak001.mp3 и netak001.txt с нумерацией от более старого выпуска к более свежему): почему именно так — скоро поймёте.
Файлы «тупо» заливаются на сервер в директорию, специально созданную для определённой передачи. Так, например, для передачи «Не так» создана директория echomskru/netak (полный путь https://eugigufo.net/echomskru/netak/), в которую залиты все «нетаковские» *.mp3 и *.txt.
Если что, дисковое пространство на сервере у меня — неограниченное.
Сразу добавлю, что ещё имеется табличка со всей необходимой информацией о выпусках передачи: тема, дата, ведущие, продолжительность по времени.

3. Какие технологии используются
Из всех имеющихся в голове автора знаний были выбраны языки PHP, HTML, CSS и XML. Все остальные языки программирования и разметки, которые могут представляться вам полезными, автору на данной стадии развития проекта таковыми не показались (а в некоторых языках он просто не силён…).

4. Готовим данные к отображению на страницах
Использование базы данных автору сразу показалось бессмысленной тратой ресурсов. Вполне достаточно создать для каждой передачи статистический xml-файл с мета-данными каждого выпуска передачи (количество выпусков-то расти не будет по причине закрытия радиостанции).
Так что в файле netaki.xml для каждого выпуска передачи прописываем вот такую конструкцию:

<vypusk ntid="netak001">
   <peredacha>Не так</peredacha>
   <veduxhie>Алексей Кузнецов и Сергей Бунтман</veduxhie>
   <data>12 апреля 2014</data>
   <dur>45:50</dur>
   <topic>Дело группы Дятлова: три тупиковых версии</topic>
</vypusk>

Как видите, в файле имеется вся информация, которую мы запланировали показывать на веб-странице архива при постановке задачи.
Обратите внимание на то, что идентификатор информации о каждом выпуске (ntid) называется так же, как и соответствующие файлы *.mp3 и *.txt. Дело в том, что далее я буду использовать идентификатор не только для «вылавливания» нужной информации из таблицы, но и для автоматического генерирования ссылок на текстовые и аудио-файлы.

5. Выводим список имеющихся в директории выпусков
Вообще-то, моя изначальная безумная идея состояла в том, что бы выводить список выпусков передачи при помощи php-функции scandir(), параллельно беря все мета-данные прямо из ID3-тэгов mp3-файлов. Код получался рабочим, очень простым, коротким и максимально универсальным — как я люблю. А вот страница с результатом его работы грузилась бесконечно долго и при наличии особенно большого количества mp3-файлов даже провоцировала безнадёжное зависание компьютера. Так что я осознал всю собственную тупость вернулся к мыслям о xml.
Как вы уже заметили выше, в xml-файле не прописаны не только имена файлов, но и абсолютные пути к ним. Во-первых, я хотел сделать файл максимально лёгким. Во-вторых, от смены адресов никто не застрахован. Так что во избежание переписывания адресов руками (и/или риска забыть это сделать в критический момент) я решил строить эти самые адреса в максимально автоматизированном режиме. Для начала мне понадобилось написать вот такое:

$protokol = (!empty($_SERVER['HTTPS']) && 'off' !== strtolower($_SERVER['HTTPS'])?"https://":"http://");
$domen = $_SERVER[SERVER_NAME];
$koren = $protokol.$domen;
$dir = 'echomskru/netak'; // папка с mp3 передач
$images = $koren.'/images/echomskru'; // путь до используемых картинок
$url = ((!empty($_SERVER['HTTPS'])) ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; // определяем url текущей страницы

Хотелось бы покороче, но я пока не придумал как.
А вот теперь можно прочитать xml-файл (о структуре которого уже было сказано выше), узнать идентификатор каждого выпуска передачи и для каждого выпуска передачи нарисовать прямоугольник-контейнер со всей полезной информацией. Обратите внимание на то, что в ссылку на mp3-файл я подставляю — как и собирался — имя идентификатора из xml-файла (см. строки 4, 7 и 17):

$xml = simplexml_load_file("$dir/netaki.xml");
$i = 0; // это значение нужно для правильного чтения xml
foreach ($xml as $vypusk) {
$path = $xml->vypusk[$i]['ntid']; // получаем идентификатор каждого выпуска передачи
$i++; // считаем количество имеющихся выпусков передачи
echo "<div class=singlevypusk><div class=singlevypuskimg>"; // div выпуска и div картинки
echo "<a href='$koren/$dir/$path.mp3'>"; // делаем ссылку на mp3 файл (для скачивания)
echo "<img src='$images/echomsknetakmptri.png' title='Скачать в формате mp3' width='100' />"; // картинка для каждого выпуска передачи
echo "</a></div>"; // закрываем ссылку на mp3 файл
echo "<div class=singlevypusktxt>";
echo 'Тема передачи: '.$vypusk->topic.'<br />'; // выведем тему выпуска
echo 'Ведущие: '.$vypusk->veduxhie.'<br />'; // выведем имена ведущих
echo 'Дата: '.$vypusk->data.'<br />'; // выведем дату эфира
echo 'Длительность: '.$vypusk->dur.'<br />'; // выведем продолжительность передачи
echo '</div>';
echo '<div class=singlevypuskpic>';
echo "<a href='$koren/$dir/$path.mp3'><img src='$images/downloadecho.png' title='Скачать в формате mp3' /></a><br />"; // делаем ссылку на mp3 файл (для скачивания)
echo "<a href='sluhainetak?search=$path'><img src='$images/sluhaiecho.png' title='Слушать на сайте' /></a><br />"; // делаем ссылку на аудио-плеер
echo "<a href='sluhainetak?search=$path'><img src='$images/chitaiecho.jpg' title='Читать стенограмму' /></a>"; // делаем ссылку на стенограмму
echo "</div></div>"; // закрываем контейнер анонса
}

Результат, который увидит посетитель на экране — серия вот таких автоматически сгенерированных блоков (прямоугольников-контейнеров):

Переменная i нужна исключительно для подсчёта количества выпусков передачи: я показываю его внизу страницы, посвящённой конкретной передаче.


6. Делаем ссылки на аудио-плеер и текстовую расшифровку
В правой части каждого блока (см. картинку выше) присутствуют три пиктограммы, значения которых, по-моему, понятны всем (или нет?). Сделать их активными — проще простого.
Как вы уже видели в третьем листинге, ссылку для скачивания конкретного выпуска передачи генерирую при помощи всё тех же переменных (включая переменную path, которая содержит идентификатор из xml-файла):

echo "<a href='$koren/$dir/$path.mp3'><img src='$images/downloadecho.png' title='Скачать в формате mp3' /></a><br />"; // делаем ссылку на mp3 файл (для скачивания)

Остаётся сделать ссылки на аудио-плеер и на текстовую расшифровку выпуска передачи. Мне показалось, что было бы удобным разместить эти материалы — плеер и расшифровку — на одной странице, поэтому ссылка в обоих случаях выглядит одинаково (тоже генерируется при помощи переменных, которые вам уже знакомы):

echo "<a href='sluhainetak?search=$path'><img src='$images/sluhaiecho.png' title='Слушать на сайте' /></a><br />"; // делаем ссылку на аудио-плеер
echo "<a href='sluhainetak?search=$path'><img src='$images/chitaiecho.jpg' title='Читать стенограмму' /></a>"; // делаем ссылку на стенограмму

Как вы можете догадаться, мне было лень создавать руками отдельную страницу для каждого из сотен выпусков передачи, поэтому страницу я создал всего одну — располагающуюся по адресу https://www.eugigufo.net/echomoskvy/netak/sluhainetak (в случае передачи «Не так»), — на которой в зависимости от запроса GET (то, что в ссылках из последнего листинга начинается со знака вопроса) будет отображаться нужная информация. Вы осилили этот пассаж? На всякий случай перечитайте.
И идём дальше.
Как я писал выше, имя идентификатора каждого выпуска в xml-таблице — такое же, как и имя соответствующего mp3-файла. Последний элемент сгенерированной при помощи переменной path ссылки «называется» так же, как и идентификатор: так что на странице с плеером и текстом нам нужно будет просто снова открыть xml-файл и найти в нём запись с совпадающим идентификатором.
Полный код страницы с выводом списка выпусков передачи и ссылками на плеер и расшифровку получается вот такой:

$protokol = (!empty($_SERVER['HTTPS']) && 'off' !== strtolower($_SERVER['HTTPS'])?"https://":"http://");
$domen = $_SERVER[SERVER_NAME];
$koren = $protokol.$domen;
$dir = 'echomskru/netak'; // папка с mp3 передач
$images = $koren.'/images/echomskru'; // путь до используемых картинок
$xml = simplexml_load_file("$dir/netaki.xml");
$i = 0; // это значение нужно для правильного чтения xml
foreach ($xml as $vypusk) {
$path = $xml->vypusk[$i]['ntid']; // получаем идентификатор каждого выпуска передачи
$i++; // считаем количество имеющихся выпусков передачи
echo "<div class=singlevypusk><div class=singlevypuskimg>"; // div выпуска и div картинки
echo "<a href='$koren/$dir/$path.mp3'>"; // делаем ссылку на mp3 файл (для скачивания)
echo "<img src='$images/echomsknetakmptri.png' title='Скачать в формате mp3' width='100' />"; // картинка для каждого выпуска передачи
echo "</a></div>"; // закрываем ссылку на mp3 файл
echo "<div class=singlevypusktxt>";
echo 'Тема передачи: '.$vypusk->topic.'<br />'; // выведем тему выпуска
echo 'Ведущие: '.$vypusk->veduxhie.'<br />'; // выведем имена ведущих
echo 'Дата: '.$vypusk->data.'<br />'; // выведем дату эфира
echo 'Длительность: '.$vypusk->dur.'<br />'; // выведем продолжительность передачи
echo '</div>';
echo '<div class=singlevypuskpic>';
echo "<a href='$koren/$dir/$path.mp3'><img src='$images/downloadecho.png' title='Скачать в формате mp3' /></a><br />"; // делаем ссылку на mp3 файл (для скачивания)
echo "<a href='sluhainetak?search=$path'><img src='$images/sluhaiecho.png' title='Слушать на сайте' /></a><br />"; // делаем ссылку на аудио-плеер
echo "<a href='sluhainetak?search=$path'><img src='$images/chitaiecho.jpg' title='Читать стенограмму' /></a>"; // делаем ссылку на стенограмму
echo "</div></div>"; // закрываем контейнер анонса
}
echo "<div style=\"clear: both\">Всего выпусков передачи: $i</div>";

Теперь, когда с выводом списка выпусков мы закончили, — переходим к работе над второй страницей. То есть над страницей, посвящённой отдельному выпуску передачи.

7. Создаём страницу с аудио-плеером и текстовой расшифровкой
Первая часть кода этой второй страницы должна уже быть вам понятна: автоматизируем работу с адресом страницы, считываем GET-запрос и вставляем код аудио-плеера с адресом mp3-файла, соответствующего запросу.

$protokol = (!empty($_SERVER['HTTPS']) && 'off' !== strtolower($_SERVER['HTTPS'])?"https://":"http://");
$domen = $_SERVER[SERVER_NAME];
$koren = $protokol.$domen;
$dir = 'echomskru/netak'; // папка с mp3 передач
$fileinfo = $_GET['search'];
$fileinfo = htmlspecialchars($fileinfo);
echo "<center><audio controls preload='auto' src='$koren/$dir/$fileinfo.mp3' type='audio/mp3'></audio></center><br />";

Загружаем xml-файл:

$xml = simplexml_load_file("$dir/netaki.xml");

Далее нам нужно перебирать элементы файла начиная с самого первого (который на самом деле пронумерован в логике xml как нулевой) в поисках того, что записан с идентификатором, соответствующим ссылке / url-у конкретного выпуска. Поэтому и пришлось написать следующую конструкцию, не забыв отдельно указать, что анализ элементов xml должен начинаться с самого первого / нулевого (i=0).

$i = 0;
foreach ($xml as $vypusk) {
$ntid = $xml->vypusk[$i]['ntid'];
$i++;
if ($ntid == $fileinfo)
{
echo '<div class=sluhainfo>'.$vypusk->topic.'<br />Дата эфира: '.$vypusk->data.'.<br />Ведущие: '.$vypusk->veduxhie.'.</div>';
$tracklist = $dir.'/'.$fileinfo.'.txt'; // файл с расшифровкой выпуска передачи
if (file_exists($tracklist)) {echo '<div class=sluhaitxt>'.file_get_contents($tracklist).'</div>';} // выведем расшифровку
else {echo 'Надо&nbsp;бы раздобыть расшифровку этого эфира. Кто возьмётся сделать?<br /><br />';}
echo "<div class=sluhainfo><a href='$koren/$dir/$fileinfo.mp3' >А&nbsp;можно и&nbsp;в&nbsp;формате MP3 скачать</a>.</div>";
}
}

А вот полный код страницы с плеером и текстовой расшифровкой выбранного посетителем выпуска передачи, если кому-то хочется оценить картину в целом:

$protokol = (!empty($_SERVER['HTTPS']) && 'off' !== strtolower($_SERVER['HTTPS'])?"https://":"http://");
$domen = $_SERVER[SERVER_NAME];
$koren = $protokol.$domen;
$dir = 'echomskru/netak'; // папка с mp3 передач
$fileinfo = $_GET['search'];
$fileinfo = htmlspecialchars($fileinfo);
echo "<center><audio controls preload='auto' src='$koren/$dir/$fileinfo.mp3' type='audio/mp3'></audio></center><br />";
$xml = simplexml_load_file("$dir/netaki.xml");
$i = 0;
foreach ($xml as $vypusk) {
$ntid = $xml->vypusk[$i]['ntid'];
$i++;
if ($ntid == $fileinfo)
{
echo '<div class=sluhainfo>'.$vypusk->topic.'<br />Дата эфира: '.$vypusk->data.'.<br />Ведущие: '.$vypusk->veduxhie.'.</div>';
$tracklist = $dir.'/'.$fileinfo.'.txt'; // файл с расшифровкой выпуска передачи
if (file_exists($tracklist)) {echo '<div class=sluhaitxt>'.file_get_contents($tracklist).'</div>';} // выведем расшифровку
else {echo 'Надо&nbsp;бы раздобыть расшифровку этого эфира. Кто возьмётся сделать?<br /><br />';} // если файла с расшифровкой нет
echo "<div class=sluhainfo><a href='$koren/$dir/$fileinfo.mp3' >А&nbsp;можно и&nbsp;в&nbsp;формате MP3 скачать</a>.</div>";
}
}

Таким образом, гипотетическое добавление в архив новых выпусков передачи — если таковые обнаружатся — потребует от меня только двух действий: загрузки файлов *.mp3 и *.txt в директорию на сервере и добавления информации о каждом новом выпуске в xml-файл.
В CSS-коде ничего интересного нет — там прописано чисто оформление элементов страниц —, так что не буду грузить вас лишней информацией.

8. Что будет дальше?
Один из поклонников передачи «Не так» спросил меня, ещё на ранней стадии разработки этого проекта, планирую ли я сделать rss feed для плееров подкастов. Идея мне кажется правильной: в этих целях я сделаю отдельный специальный xml-файл (или переделка существующего ничему не повредит?), но всё это — отдельная большая тема. Мне для rss ещё с чьей-то помощью нужно будет все необходимые скрипты дописать…
Ну а теперь, уважаемые читатели-разработчики, — вам слово! Что можно улучшить? Что следует добавить?
Предложения и пожелания принимаются на почту e.sytchev@gmail.com.

Прокомментировать