IAVG-HTML - Приложение для удобного просмотра gif и webm сборников в браузере

Приложение Image and Video Gallery (IAVG-HTML) предназначено для автоматического создания HTML-галереи изображений и видеофайлов, находящихся в текущей директории. Оно генерирует веб-страницу, на которой вы можете удобно просматривать контент.

Предисловие

Ещё с давних времён, завалялся у меня сборник gif-ок на CD-диске, решил я в нем покопаться, однако нормально посмотреть содержимое не удалось. Встроенный в современные операционные системы просмотрщик не анимирует gif-файлы при просмотре. Открывать в браузере по одной анимации - то ещё удовольствие. Плюсом подвернулся архив коротких webm-фалов, с которыми аналогичная проблема. Так в поисках решения для удобного просмотра подобного контента было разработано следующее приложение. Выполняя приложение в папке с контентом - получаем html-файл, запускаем его в браузере и получаем просмотр аля “Shorts”. Делюсь своими наработками.

Функциональные возможности

  • Автоматическое сканирование текущей директории на наличие файлов изображений и видео.
  • Поддержка форматов: JPG, JPEG, PNG, GIF, WEBM.
  • Создание адаптивной HTML-страницы с удобной навигацией.
  • Ленивая загрузка изображений и видео для оптимизации скорости работы.
  • Плавная прокрутка между элементами галереи.
  • Быстрый переход к конкретному файлу по его порядковому номеру.
  • Поддержка управления клавишами (ArrowUp и ArrowDown).

Принцип работы

  1. Приложение сканирует текущую папку на наличие поддерживаемых файлов.
  2. Создаёт HTML-файл с галереей, где каждый файл представлен в отдельной секции.
  3. Готовый HTML-файл сохраняется под именем "!outputap.html".

Как использовать

  1. Сохраните Python-скрипт и запустите его в каталоге с изображениями и видео.
  2. После выполнения скрипта откройте сгенерированный файл "!outputap.html" в браузере.
  3. Используйте клавиши управления или поле ввода для навигации по галерее.

Код:


import os

# Название выходного HTML-файла
output_file = "!outputap.html"

# Начало HTML-файла
html_content = """
<html>
<head>
    <title>Image and Video Gallery</title>
    <style>
        body, html {
            margin: 0;
            padding: 0;
            height: 100%;
            overflow: hidden;
            font-family: Arial, sans-serif;
        }
        .container {
            scroll-snap-type: y mandatory;
            overflow-y: scroll;
            height: 100vh;
            padding: 5px; /* Отступ от краев браузера */
            box-sizing: border-box; /* Учитываем padding в размерах */
        }
        .frame {
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            width: 100%;
            max-width: 1600px;
            height: calc(100vh - 10px); /* Учитываем отступы */
            margin: 0 auto;
            border: 2px solid #ccc;
            box-sizing: border-box;
            overflow: hidden;
            padding: 5px; /* Отступ от границ блока */
        }
        .content {
            max-width: 100%;
            max-height: 100%;
            display: flex;
            justify-content: center;
            align-items: center;
            flex-grow: 1;
        }
        .content img, .content video {
            max-width: 100%;
            max-height: 100%;
            object-fit: contain;
        }
        .section {
            height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
            scroll-snap-align: start;
        }
        h2 {
            text-align: center; /* Заголовок по центру */
            margin: 0; /* Убираем margin */
            padding-top: 7px; /* Отступ сверху 7px (5px + 2px) */
            box-sizing: border-box; /* Учитываем padding в размерах */
        }
        /* Плавающий блок с элементами управления */
        .controls {
            position: fixed;
            bottom: 30px; /* Учитываем отступ от краев браузера */
            right: 30px; /* Учитываем отступ от краев браузера */
            background: rgba(255, 255, 255, 0.8);
            padding: 10px;
            border-radius: 5px;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
            display: flex;
            flex-direction: column;
            gap: 10px;
        }
        .controls input {
            padding: 5px;
            font-size: 16px;
            width: 100px;
        }
        .controls button {
            padding: 5px 10px;
            font-size: 16px;
            cursor: pointer;
        }
    </style>
</head>
<body>
<div class="container">
    <h1 style="text-align: center; padding: 20px;">Image and Video Gallery</h1>
"""

# Счетчик для порядкового номера контента
counter = 1

# Поиск .gif, .webm, .jpg, .jpeg и .png файлов в текущей папке
for file in os.listdir("."):
    if file.lower().endswith((".gif", ".webm", ".jpg", ".jpeg", ".png")):
        html_content += f"""
    <div class="section">
        <div class="frame">
            <h2>{counter}. {file}</h2> <!-- Добавлен порядковый номер -->
"""
        if file.lower().endswith(".gif"):
            html_content += f"""
            <div class="content">
                <img data-src="{file}" alt="{file}">
            </div>
"""
        elif file.lower().endswith(".webm"):
            html_content += f"""
            <div class="content">
                <video controls loop autoplay muted data-src="{file}">
                    Your browser does not support the video tag.
                </video>
            </div>
"""
        elif file.lower().endswith((".jpg", ".jpeg", ".png")):
            html_content += f"""
            <div class="content">
                <img data-src="{file}" alt="{file}">
            </div>
"""
        html_content += """
        </div>
    </div>
"""
        counter += 1  # Увеличиваем счетчик

# Конец HTML-файла
html_content += """
</div>
<!-- Плавающий блок с элементами управления -->
<div class="controls">
    <input type="number" id="sectionNumber" placeholder="Номер" min="1" />
    <button onclick="goToSection()">Перейти</button>
</div>
<script>
    // Функция для перехода к конкретному номеру контента
    function goToSection() {
        const sectionNumber = parseInt(document.getElementById('sectionNumber').value);
        if (sectionNumber >= 1) {
            const targetSection = document.querySelector(`.section:nth-child(${sectionNumber + 1})`);
            if (targetSection) {
                targetSection.scrollIntoView({ behavior: 'smooth' });
            }
        }
    }

    // Обработка клавиш для прокрутки
    document.addEventListener('keydown', function(event) {
        if (event.key === 'ArrowDown') {
            window.scrollBy({ top: window.innerHeight, behavior: 'smooth' });
        } else if (event.key === 'ArrowUp') {
            window.scrollBy({ top: -window.innerHeight, behavior: 'smooth' });
        }
    });

    // Ленивая загрузка с использованием Intersection Observer
    const observer = new IntersectionObserver((entries) => {
        entries.forEach(entry => {
            if (entry.isIntersecting) {
                const content = entry.target.querySelector('.content');
                if (content) {
                    const img = content.querySelector('img');
                    const video = content.querySelector('video');
                    if (img && img.dataset.src) {
                        img.src = img.dataset.src; // Загружаем изображение
                    }
                    if (video && video.dataset.src) {
                        video.innerHTML = `<source src="${video.dataset.src}" type="video/webm">`; // Загружаем видео
                    }
                }
                observer.unobserve(entry.target); // Прекращаем наблюдение после загрузки
            }
        });
    }, { threshold: 0.5 }); // Порог видимости 50%

    // Наблюдаем за всеми секциями
    document.querySelectorAll('.section').forEach(section => {
        observer.observe(section);
    });
</script>
</body>
</html>
"""

# Сохранение HTML-файла
with open(output_file, "w", encoding="utf-8") as f:
    f.write(html_content)

print(f"HTML-файл '{output_file}' успешно создан.")

Минимальные системные требования

Для выполнения в виде скрипта

  • Операционная система: Windows 7/8/10/11, Linux, macOS
  • Python 3.6 или выше

Для выполнения в виде скомпилированного приложения

  • Операционная система: Windows 7/8/10/11

Заключение

Приложение IAVG-HTML — это удобный инструмент для быстрого создания HTML-галерей. Оно автоматически формирует удобную навигацию и обеспечивает плавный просмотр контента. Скомпилированная версия приложения, будет размещена в загрузках.

Alecsey 2025-03-14