diff --git a/.idea/AnimeVideoEditot.iml b/.idea/AnimeVideoEditot.iml index 8746ecd..5e38f9c 100644 --- a/.idea/AnimeVideoEditot.iml +++ b/.idea/AnimeVideoEditot.iml @@ -4,7 +4,7 @@ - + diff --git a/.idea/material_theme_project_new.xml b/.idea/material_theme_project_new.xml index ec7f734..1f861cc 100644 --- a/.idea/material_theme_project_new.xml +++ b/.idea/material_theme_project_new.xml @@ -3,8 +3,15 @@ + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 24f69a0..c0e76d1 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -3,5 +3,5 @@ - + \ No newline at end of file diff --git a/README.md b/README.md index 0de00b1..617a4d4 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,22 @@ # Anime Video Editor -Приложение для объединения нескольких видео в один файл. Поддерживает выбор временных диапазонов для каждого ролика, настройку формата (MP4, AVI, MOV, MKV) и качества экспорта. \ No newline at end of file +Приложение для объединения нескольких видео в один файл. Поддерживает выбор временных диапазонов для каждого ролика, настройку формата (MP4, AVI, MOV, MKV) и качества экспорта. + +## Сборка в exe (Windows) + +1. Установите зависимости проекта и сборки (обязательно в том же окружении, где будете запускать PyInstaller): + ```bash + pip install -r requirements.txt + pip install -r requirements-build.txt + ``` +2. Соберите exe: + ```bash + pyinstaller --noconfirm AnimeVideoEditor.spec + ``` + или запустите скрипт: + ```powershell + .\build_exe.ps1 + ``` +3. Готовый файл: `dist\AnimeVideoEditor.exe` (один файл, консоль не показывается). + +FFmpeg включается в сборку автоматически (через imageio_ffmpeg). \ No newline at end of file diff --git a/asets/icon.png b/asets/icon.png new file mode 100644 index 0000000..3ee95f8 Binary files /dev/null and b/asets/icon.png differ diff --git a/build_exe.ps1 b/build_exe.ps1 new file mode 100644 index 0000000..c5adbc7 --- /dev/null +++ b/build_exe.ps1 @@ -0,0 +1,27 @@ +# Build Anime Video Editor to exe (Windows) +# Run: .\build_exe.ps1 + +$ErrorActionPreference = "Stop" +Set-Location $PSScriptRoot + +Write-Host "Checking project dependencies..." -ForegroundColor Cyan +pip install -r requirements.txt -q +if (-not $?) { exit 1 } +Write-Host "Checking PyInstaller..." -ForegroundColor Cyan +pip show pyinstaller 2>$null | Out-Null +if ($LASTEXITCODE -ne 0) { + Write-Host "Installing PyInstaller..." -ForegroundColor Yellow + pip install pyinstaller +} + +Write-Host "Building exe..." -ForegroundColor Cyan +pyinstaller --noconfirm AnimeVideoEditor.spec + +if (Test-Path "dist\AnimeVideoEditor.exe") { + Write-Host "" + Write-Host "Done: dist\AnimeVideoEditor.exe" -ForegroundColor Green +} else { + Write-Host "" + Write-Host "Build failed. Check output above." -ForegroundColor Red + exit 1 +} diff --git a/core/video_processor.py b/core/video_processor.py index 2c96501..ceab7c9 100644 --- a/core/video_processor.py +++ b/core/video_processor.py @@ -1,7 +1,9 @@ import os import subprocess +import sys import tempfile import warnings +import glob from moviepy import VideoFileClip, concatenate_videoclips from moviepy.video.fx import Resize from datetime import datetime @@ -53,7 +55,14 @@ warnings.filterwarnings( def _get_ffmpeg_exe(): - """Путь к FFmpeg (тот же, что использует MoviePy/imageio).""" + """Путь к FFmpeg (тот же, что использует MoviePy/imageio). В exe (PyInstaller) — из папки сборки.""" + if getattr(sys, "frozen", False) and getattr(sys, "_MEIPASS", None): + base = sys._MEIPASS + for folder in ("imageio_ffmpeg", "."): + search = os.path.join(base, folder, "*.exe") + for path in glob.glob(search): + if "ffmpeg" in os.path.basename(path).lower(): + return path try: import imageio_ffmpeg return imageio_ffmpeg.get_ffmpeg_exe() diff --git a/gui/main_window.py b/gui/main_window.py index 8d4df7e..4db3130 100644 --- a/gui/main_window.py +++ b/gui/main_window.py @@ -12,6 +12,12 @@ import sys import subprocess +def _icon_path(): + if getattr(sys, "frozen", False) and getattr(sys, "_MEIPASS", None): + return os.path.join(sys._MEIPASS, "asets", "icon.png") + return os.path.join(os.path.dirname(os.path.dirname(__file__)), "asets", "icon.png") + + class MainWindow: def __init__(self, root): self.root = root @@ -19,6 +25,12 @@ class MainWindow: self.root.geometry("1000x780") self.root.minsize(800, 600) self.root.configure(bg=COLORS["bg"]) + try: + _path = _icon_path() + if os.path.isfile(_path): + self.root.iconphoto(True, tk.PhotoImage(file=_path)) + except Exception: + pass setup_theme(root) self.video_items = [] diff --git a/pyi_hooks/hook-moviepy.py b/pyi_hooks/hook-moviepy.py new file mode 100644 index 0000000..e8dac22 --- /dev/null +++ b/pyi_hooks/hook-moviepy.py @@ -0,0 +1,5 @@ +# PyInstaller hook: force moviepy into the bundle +from PyInstaller.utils.hooks import collect_all, collect_submodules + +datas, binaries, hiddenimports = collect_all("moviepy") +hiddenimports += list(collect_submodules("moviepy")) diff --git a/requirements-build.txt b/requirements-build.txt new file mode 100644 index 0000000..a3636c8 --- /dev/null +++ b/requirements-build.txt @@ -0,0 +1,2 @@ +# Для сборки exe (установить: pip install -r requirements-build.txt) +pyinstaller>=6.0.0 diff --git a/requirements.txt b/requirements.txt index de870a8..3160637 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,3 @@ -# Видеоредактор — зависимости (Windows и Linux) -# Используются версии с готовыми wheel-пакетами для обеих платформ. +# Anime Video Editor - dependencies (Windows and Linux) moviepy>=1.0.3 Pillow>=10.1.0