Данная статья создана исключительно в информационно-ознакомительных целях. Автор не призывает читателей повторять описанный опыт.
У Яндекса, как и у многих других, есть файловое хранилище под названием Яндекс Диск. Помимо прочего, данный сервис позволяет хранить и воспроизводить видео. Более того, при наличии подписки Яндекс 360 появляется возможность тонкой настройки безопасности при распространении публичных ссылок на файлы. В число таких настроек входит:
- Пароль, который потребуется для просмотра файла:
- Невозможность скачивания файла и сохранения его к себе на Диск:
- Срок действия публичной ссылки на файл.
Среди вышеперечисленного меня заинтересовала невозможность скачать файлы по предоставленной публичной ссылке. Неплохая заявка на «защиту» от копирования материалов, которые нужно кому-либо показать, но не «отдавать». Проверим как это выглядит…
Подготовка
Я купил подписку Яндекс 360 на месяц (199 руб/мес. без всяких скидок на 07.01.2024) и сразу отключил ее. Если этого не сделать, то будет включено автоматическое продление, которое, очевидно, мне без надобности.
Далее нужен какой-нибудь сайт, который даст возможность скачать небольшое видео без лицензионных ограничений. как раз для таких целей есть данный сайт, где я скачал «Проезжающий мимо парка поток автотранспорта» длительностью 15 секунд и размером 12 Мб — то, что надо. Теперь необходимо загрузить видео на Диск. Подробно на этой части останавливаться не буду.
Для последующего анализа потребуется сделать данное видео публичным и запретить его скачивание. В контекстном меню (ПКМ1 на файле) выбираю «Поделиться», включаю запрет на скачивание и копирую ссылку.
Чтобы не выходить из своей учетной записи открываю ссылку в новом инкогнито окне браузера и вижу готовый к воспроизведению проигрыватель.
Ниже для сравнения показываю как выглядит страница с проигрывателем без включенного запрета на скачивание и с ним.
Анализ получения данных
Поглядим откуда берется видеопоток. Открываю инструменты разработчика в браузере (F12), а точнее вкладку для анализа сетевого трафика (Network). Запускаю воспроизведение и смотрю видео до конца (оно же короткое) чтобы записались все сетевые запросы. После этого останавливаю запись сетевых запросов чтобы не появлялось лишнего мусора.
В зависимости от длины и качества видео будет различное количество итоговых запросов:
Среди всего этого разнообразия нам необходимы лишь те запросы, которые показывают загрузку чего-либо. Для этого имеется возможность применить фильтр «Fetch/XHR» (одна из кнопок над списком запросом). Отфильтрованный перечень запросов выглядит уже лучше. Более того, сразу можно увидеть те запросы, ответ в которых содержал максимальное количество информации (по размеру):
Забегая немного вперед, сразу скажу, что если перейти в браузере по адресу любого из указанных выше запросов, то будет предложено сохранить некий файл с расширением *.ts
. При сохранении станет ясно, что это видеофайл, а если точнее, то фрагмент видео, которое воспроизводилось. Очевидно, что другой запрос также является фрагментом воспроизведенного видео. Единственный недостаток сохраненного файла (не считая того, что видео неполное) – отвратительное качество. Во время просмотра видео в проигрывателе было установлено качество 240p. Устанавливаю 720p и повторяю процедуру записи сетевых пакетов.
При сравнении между собой полных адресов запросов первой (240p) и второй (720p) попытки записи сетевых пакетов (сравнивать можно тут) получается следующий паттерн:
Если выкинуть все параметры запроса после предполагаемого идентификатора видео и перейти в браузере по оставшемуся адресу, подставив максимальный порядковый номер видео фрагмента, то браузер предлагает сохранить последний фрагмент видео в указанном качестве!
Уже на данном этапе можно заявить, что при должном уровне терпения удастся скачать полное видео, разделенное на несколько файлов/фрагментов.
Автоматизация процесса скачивания
Процесс скачивания всего видео заключается в последовательном выполнении запросов по загрузке фрагментов видео по их порядковому номеру. С данной задачей прекрасно справится утилита curl. При помощи следующей команды можно скачать в текущую директорию один фрагмент (под порядковым номером 3) видео в качестве 720p, сохранив его с именем output3.ts
:
:: Некоторые части ссылки сокращены для удобства восприятия
curl -o output3.ts "https://streaming.disk.yandex.net/hls/.../720p/3.ts?from=disk&vsid=..."
Для автоматизации процесса загрузки всех фрагментов видео я набросал скрипт для командной оболочки Windows:
@ECHO OFF
SETLOCAL
:: Данная переменная хранит стартовый адрес загрузки фрагмента видео
:: вплоть до порядкового номера фрагмента, ВКЛЮЧАЯ качество видео
SET PRE_URL="https://streaming.disk.yandex.net/hls/.../720p/"
:: Данная переменная хранит часть адреса загрузки фрагмента видео,
:: которая идет сразу после порядкового номера фрагмента
:: и заканчивается идентификатором видео (до знака &, не включая его)
SET POST_URL=".ts?from=disk&vsid=..."
:: Переменная наименования директории, в которую будут сохранены фрагменты
SET DOWNLOAD_DIR=output
:: Создание директории для сохранения фрагментов
MKDIR %DOWNLOAD_DIR%
:: Запуск цикла скачивания каждого фрагмента по порядку,
:: начиная с 1 и заканчивая 3 с шагом равным 1.
:: Каждый фрагмент будет сохранен в указанную выше директорию
:: с именем output<порядковый номер>.ts
:: Синтаксис %PRE_URL:"=% указывает на переменную PRE_URL,
:: из которой удалены символы кавычек
FOR /L %%A IN (1,1,3) DO (
curl -o %DOWNLOAD_DIR%\output%%A.ts "%PRE_URL:"=%%%A%POST_URL:"=%"
)
После запуска скрипта получаем фрагментированное видео, для которого установлен запрет на скачивание!
Объединение фрагментов
Для работы с видео из консоли есть прекрасная утилита ffmpeg, которая позволяет одной простой командой объединить несколько фрагментов видео в единый файл.
Скачать ffmpeg для своей операционной системы можно отсюда. Для объединения фрагментов ffmpeg предлагает 2 метода:
Для данного метода потребуется файл, в котором будут перечислены имена файлов всех фрагментов для объединения в следующем формате:
# Это комментарий
file '/путь/до/output1.ts' # Для Windows: 'С:\путь\до\output1.ts'
file '/путь/до/output2.ts'
file '/путь/до/output3.ts'
После создания файла достаточно запустить ffmpeg следующей командой:
:: -f concat - метод объединения demuxer
:: -safe 0 - проверка пути до указываемого файла
:: -i files.txt - абсолютный или относительный путь до созданного ранее файла
:: -c copy - создание итогового файла безе перекодирования видео/аудио потоков
:: output_full.mp4 - имя итогового файла
ffmpeg -f concat -safe 0 -i files.txt -c copy output_full.mp4
При указании относительного пути до files.txt
параметр -safe 0
можно не указывать.
При использовании этого метода никаких файлов не нужно, достаточно использовать специальный синтаксис при запуске ffmpeg:
:: Возможно, потребуется экранировать разделитель между файлами,
:: т.к. он является специальным для некоторых оболочек
ffmpeg -i "concat:/путь/до/output1.ts|/путь/до/output2.ts|/путь/до/output3.ts" -c copy output_full.mp4
Внимание! При использовании любого из методов важно корректно указывать порядок входящих файлов, т.к. объединение производится именно в указанном порядке.
При объединении фрагментов, закодированных различными кодеками, процесс усложняется. Подробнее здесь.
Для себя я выбрал первый метод. Осталось только сгенерировать корректный файл. Набросал простенькую программу на Java:
import java.nio.charset.*;
import java.nio.file.*;
import java.util.*;
import java.util.regex.*;
import java.util.stream.*;
public class VideoMerger {
// Паттерн регулярного выражения, который предполагает имя файла
// с порядковым номером непосредственно перед расширением
private static final Pattern INPUT_FILE_PATTERN = Pattern.compile("^.*?(\\d+)\\.[A-Za-z-_]+$");
public static void main(String[] args) throws Exception {
// Получение потока файлов из директории, которая передается первым аргументом к программе
try (Stream<Path> filesStream = Files.walk(Paths.get(args[0]), 1)) {
List<String> fileList = filesStream.filter(path -> !path.toFile().isDirectory()) // оставляем только файлы
// Сортировка файлов
.sorted((o1, o2) -> {
// Применение указанного выше паттерна к каждой паре файлов
Matcher m1 = INPUT_FILE_PATTERN.matcher(o1.getFileName().toString());
Matcher m2 = INPUT_FILE_PATTERN.matcher(o2.getFileName().toString());
m1.find();
m2.find();
// Выделение целочисленного порядкового номера из каждого файла в парах
int i1 = Integer.parseInt(m1.group(1));
int i2 = Integer.parseInt(m2.group(1));
// Сортировка файлов по возрастанию порядкового номера
return i1 - i2;
})
// Приведение каждого файла к требуемому формату для дескриптора
.map(path -> "file '" + path.toAbsolutePath().toString() + "'")
// Сборка к коллекцию
.collect(Collectors.toList());
// Запись файла-дескриптора для ffmpeg
Files.write(Paths.get(args[1], "files.txt"), fileList, StandardCharsets.UTF_8);
}
}
}
Данную программу необходимо сохранить в файле VideoMerger.java
. После этого потребуется открыть консоль в директории, где был сохранен данный файл, скомпилировать исходный код в исполняемый и запустить программу:
Установка и настройка JDK для компиляции и запуска Java программ выходит за рамки данной статьи.
:: Компилируем исходный код
javac VideoMerger.java
:: Запускаем программу
java VideoMerger "/путь/до/загруженных/фрагментов" "/путь/для/сохранения/дескриптора/ffmpeg"
На выходе будет готовый файл-дескриптор для работы ffmpeg:
Осталось запустить ffmpeg:
ffmpeg.exe -f concat -safe 0 -i D:\...\...\output\files.txt -c copy D:\...\...\output\output_full.mp4
По итогу получаем полное видео в указанном качестве!
Заключение
Выходит, что не получилось у Диска защитить мое «ценное» видео. Возможно, описанные выше действия не подойдут обычному пользователю, но и сложным процесс скачивания назвать нельзя.
Напомню, что возможность «защитить» свои файлы от копирования входит в платную подписку. Более того, об этой возможности явно заявляется, как о преимуществе, при сравнении платной и бесплатной версии Диска.
Информация к размышлению. Публичная ссылка работает сразу после нажатия на «Поделиться». При этом по умолчанию публичная ссылка бессрочна. Что будет с защитой от скачивания после прекращения действия подписки? Люди, у которых есть ссылка смогут скачать файлы?
Полезные ссылки
- https://samplelib.com/ru/ — библиотека тестовых файлов
- https://text-compare.com/ — сравнение двух текстовых файлов
- https://ffmpeg.org/ — кроссплатформенный инструмент для работы с видео и аудио
- Правая кнопка мыши ↩︎