Прекратить диапазон загрузки по сбою (загружен пустой файл)

Вопрос или проблема

Сегодня я узнал, что могу загружать несколько файлов в диапазоне с помощью curl, и это здорово.

$ curl -O "http://example.com/[001-100].png" (https://everything.curl.dev/cmdline/globbing)

Также я узнал, что могу использовать флаг -f, чтобы предотвратить сохранение пустых файлов, если файл отсутствует (допустим, мы проверяем все файлы в диапазоне 001-100, но есть только файлы с 001 по 050).

Проблема, с которой я столкнулся, заключается в том, что мой диапазон действительно большой. Я хочу сохранить некоторые видео из онлайн-трансляции (и они разделены примерно на 5 секунд, чтобы потом объединить их в одно видео с помощью моего скрипта). Диапазон равен примерно 00001-10000, но некоторые видео очень короткие (00001-00100).

Мне нужен способ остановить попытки загрузки видеофайлов, когда возвращаемый файл пуст, вместо игнорирования этого случая. Что-то вроде цикла/прерывания.

Возможно ли это с помощью curl? У вас есть предложения? (Я просто хочу сохранить все существующие в этом диапазоне 00001-10000 фрагменты видео, но прекратить попытки загрузки, когда ничего больше не найдено).

Обновление:

Контекст: длинное видео разделено на маленькие .ts фрагменты и его части названы последовательными числами. Если 070 является допустимым файлом, а 071 пуст, это означает, что видео имеет только 70 частей, которые я буду объединять. Это мои окончательные шаги для получения видео в виде одного файла после загрузки частей.

$ printf "file '%s'\n" ./*.ts > mylist.txt

$ ffmpeg -f concat -safe 0 -i mylist.txt -c copy final-video.ts

Я думаю, что вам нужно было --fail-early в комбинации с -f (--fail), так что:

curl -O "http://example.com/[001-100].png" 
# но есть только 50 изображений, так что не пробовать 51-100 ...

# используйте это
curl --fail \
     --fail-early \
     -O "http://example.com/[001-100].png"

Затем curl попробует 051.png, но сервер его не имеет. Он завершится с ошибкой и с --fail-early также не станет пытаться загрузить 052.png ...

Если вы хотите получить “html страницу ошибки”, возвращаемую сервером, используйте --fail-with-body вместо --fail. Тогда файл 051.png будет фактически html файлом со страницей ошибки.

Решено с помощью for/if/break.

#!/bin/bash
URL_prefix='http://example.com/filename_'
URL_var_range_start=1
URL_var_range_stop=10000
URL_var_range_zero_padding=5
URL_sufix='.ts'

echo "Создание папки для видео..."
mkdir videos && cd "$_"

echo "Создание папки видео..."
mkdir video && cd "$_"

echo "Загрузка ts файлов..."
for i in $(seq -f "%0"$URL_var_range_zero_padding"g" $URL_var_range_start $URL_var_range_stop)
do
  DOWNLOAD_URL=$URL_prefix$i$URL_sufix
  SAVED_FILE="video_"$i".ts"
  CURL_COMMAND="curl -f -s "$DOWNLOAD_URL" -o "$SAVED_FILE
  if $CURL_COMMAND; then
    echo "Загрузка "$SAVED_FILE"..."
  else
    echo "Больше нет файлов для загрузки."
    break
  fi;
done

echo "Создание плейлиста mylist.txt..."
printf "file '%s'\n" ./*.ts > mylist.txt

echo "Сохранение видеофайлов в единственный файл final-video.ts..."
ffmpeg -f concat -safe 0 -i mylist.txt -c copy final-video.ts

echo "Очистка ненужных файлов..."
rm video*.* mylist.txt

Когда файлы загружены, возможно, вы захотите concat с настоящим файлом плейлиста .m3u.

Это предназначено для файлов .ts. Я сталкивался с ситуациями, когда объединение многих файлов .ts с помощью обычной конкатенации могло привести к рассинхронизации звука или полностью сбою воспроизведения видео.

#!/bin/bash

# Проверить наличие .ts файлов
if ls *.ts 1> /dev/null 2>&1; then
    # Создать список с заголовком EXTINF для .ts файлов
    printf "#EXTINF:5.000,\n%s\n" ./*.ts > mylist.m3u

    # Вставить необходимые строки-заголовки в начало плейлиста
    sed -i '1i #EXTM3U\n#EXT-X-TARGETDURATION:12\n#EXT-X-ALLOW-CACHE:YES\n#EXT-X-PLAYLIST-TYPE:VOD\n#EXT-X-VERSION:3\n#EXT-X-MEDIA-SEQUENCE:1' mylist.m3u

    # Добавить завершающую строку в плейлист
    echo "#EXT-X-ENDLIST" >> mylist.m3u
else
    echo "Нет .ts файлов."
fi

Это создаст .m3u плейлист:

#EXTM3U
#EXT-X-TARGETDURATION:12
#EXT-X-ALLOW-CACHE:YES
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:1
#EXTINF:5.000,
video1.ts
#EXTINF:5.000,
video2.ts
#EXTINF:5.000,
video3.ts
#EXT-X-ENDLIST

Тогда вам просто нужно использовать ffmpeg, как стандартный входной файл:

ffmpeg -i mylist.m3u -c copy myfile.mp4

Если пути к файлам плейлиста относятся к URL, например https://example.com/video1.ts, вы также можете использовать ffmpeg для копирования его в файл, но вам потребуется -protocol_whitelist.

ffmpeg -protocol_whitelist file,http,https,tcp,tls -i mylist.m3u -c copy myfile.mp4

Я много раз делал это. Надеюсь, это поможет тем, кто работает с .ts файлами.

.

Ответ или решение

Конечно, давайте подробно разберем решение вашей задачи с использованием curl и обработки .ts файлов.

Проблема

Вы хотите загрузить серию видеофрагментов формата .ts, размещенных на сервере, используя curl. Эти файлы последовательно пронумерованы, например: video_00001.ts, video_00002.ts и так далее. Но ваш диапазон файлов может быть значительно больше, чем фактически существует, и вы хотите остановить закачку при первом отсутствии файла (когда возвращается пустой файл).

Решение с использованием curl

Для эффективного управления закачками и предостережения загрузки несуществующих файлов, можно использовать комбинацию аргументов CLI --fail и --fail-early. Это позволяет curl остановить попытки загрузки как только будет обнаружена ошибка (например, 404 Not Found для файла, который сервер не содержит).

Однако, более гибкий подход вы можете реализовать на скриптах bash, где можно контролировать процесс закачки более детально:

#!/bin/bash
URL_prefix='http://example.com/filename_'
range_start=1
range_stop=10000
padding=5
file_suffix='.ts'

echo "Создаем каталог для видео..."
mkdir videos && cd "$_"

echo "Скачиваем файлы .ts..."
for i in $(seq -f "%0${padding}g" $range_start $range_stop)
do
  download_url="$URL_prefix$i$file_suffix"
  saved_file="video_$i.ts"
  if curl -f -s "$download_url" -o "$saved_file"; then
    echo "Скачан файл $saved_file..."
  else
    echo "Нет больше файлов для загрузки."
    break
  fi
done

echo "Создаем плейлист mylist.txt..."
printf "file '%s'\n" ./*.ts > mylist.txt

echo "Объединяем видеофайлы в один final-video.ts..."
ffmpeg -f concat -safe 0 -i mylist.txt -c copy final-video.ts

echo "Удаляем временные файлы..."
rm video_*.ts mylist.txt

Использование плейлиста M3U

Вы можете создать M3U плейлист для слияния всех .ts файлов, что пригодится для корректного воспроизведения или дальнейшего объединения:

#!/bin/bash

if ls *.ts 1> /dev/null 2>&1; then
  printf "#EXTINF:5.000,\n%s\n" ./*.ts > mylist.m3u
  sed -i '1i #EXTM3U\n#EXT-X-TARGETDURATION:12\n#EXT-X-ALLOW-CACHE:YES\n#EXT-X-PLAYLIST-TYPE:VOD\n#EXT-X-VERSION:3\n#EXT-X-MEDIA-SEQUENCE:1' mylist.m3u
  echo "#EXT-X-ENDLIST" >> mylist.m3u
else
  echo "Файлы .ts не найдены."
fi

Затем для конкатенации:

ffmpeg -i mylist.m3u -c copy myfile.mp4

Заключение

Используя вышеописанный подход, вы не только загрузите необходимые файлы, но и оптимизируете процесс, избежав лишних попыток закачки и возможных ошибок. Это не только сэкономит вам время, но и повысит эффективность обработки видео.

Оцените материал
Добавить комментарий

Капча загружается...