Files
designloves2-itda/install_standalone.ps1
Designloves2andClaude Sonnet 5 70733382fb Fix media/project delete dialogs, add librosa, split Transition from Auto Stitch
- Replace native confirm()/alert() with the app's own modal for media and
  project deletion - a browser-owned dialog can be silently suppressed
  inside a cross-origin/sandboxed iframe (e.g. the ComfyUI preview node),
  which read as "delete does nothing"
- Add librosa to standalone dependencies (pyproject.toml, install/update
  scripts) - AI Detect's beat tracking needs it and standalone was missing
  it entirely (ComfyUI's own env already had it, masking the gap)
- Revert Auto Stitch to plain hard-cut only, no transition options
- Add a separate Transition feature: select 2 adjacent clips, choose a
  type/duration, and it overlaps them (moving B to a free lane) with a
  shared group_id so dragging one drags both - keeping the overlap intact
  instead of silently breaking on an independent move. The same button
  becomes "Remove Transition" for an existing linked pair, unwinding back
  to a plain adjacent cut.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 07:33:35 +09:00

163 lines
8.0 KiB
PowerShell

#Requires -Version 5.1
<#
Installs a self-contained standalone copy of ITDA - its own Python embeddable
runtime, its own ffmpeg, and a desktop shortcut - so it runs independently of
ComfyUI. This script is meant to be launched via Install_ITDA_Standalone.bat,
which lives next to it in the ComfyUI-ITDA custom node folder.
Nothing here touches the ComfyUI installation this node is running inside of;
everything it downloads/builds goes into the install path the user chooses.
#>
$ErrorActionPreference = "Stop"
$RepoUrl = "https://github.com/designloves2/itda.git"
$RepoZipUrl = "https://github.com/designloves2/itda/archive/refs/heads/main.zip"
Write-Host ""
Write-Host "=== ITDA Standalone Installer ===" -ForegroundColor Cyan
Write-Host "This copies ITDA out of ComfyUI's custom_nodes folder into its own"
Write-Host "self-contained install - its own Python, its own ffmpeg - so it can"
Write-Host "run on its own, without ComfyUI, as a local video editor."
Write-Host ""
$DefaultInstallPath = Join-Path $env:USERPROFILE "ITDA-Standalone"
$InstallPath = Read-Host "Install to [$DefaultInstallPath]"
if ([string]::IsNullOrWhiteSpace($InstallPath)) { $InstallPath = $DefaultInstallPath }
$InstallPath = $InstallPath.TrimEnd('\', '/')
if (Test-Path $InstallPath) {
$existing = Get-ChildItem $InstallPath -ErrorAction SilentlyContinue
if ($existing) {
$answer = Read-Host "`"$InstallPath`" already exists and isn't empty. Continue and update it in place? (y/N)"
if ($answer -notin @('y', 'Y')) { Write-Host "Cancelled."; exit 0 }
}
}
New-Item -ItemType Directory -Force -Path $InstallPath | Out-Null
# ---------------------------------------------------------------------------
# The install folder becomes an actual git checkout of the published repo
# (not a copy of whatever's locally sitting in custom_nodes) whenever git is
# available - that's what makes Update_ITDA_Standalone.bat later just a
# `git pull`, matching the intended custom-node-fix -> push -> standalone
# update workflow. Falls back to a one-shot zip snapshot when git isn't
# installed (update then re-downloads instead of incrementally pulling).
$GitAvailable = [bool](Get-Command git -ErrorAction SilentlyContinue)
$IsExistingGitCheckout = Test-Path (Join-Path $InstallPath ".git")
$InstallPathEmpty = -not (Get-ChildItem $InstallPath -ErrorAction SilentlyContinue)
Write-Host ""
if ($GitAvailable -and $IsExistingGitCheckout) {
Write-Host "[1/6] Pulling latest ITDA source (git)..." -ForegroundColor Cyan
Push-Location $InstallPath
git pull --ff-only origin main
Pop-Location
} elseif ($GitAvailable -and $InstallPathEmpty) {
Write-Host "[1/6] Cloning ITDA source from GitHub..." -ForegroundColor Cyan
git clone --branch main $RepoUrl $InstallPath
} else {
if ($GitAvailable) {
Write-Host "[1/6] Install folder has existing non-git content - downloading a source snapshot instead of cloning." -ForegroundColor Yellow
} else {
Write-Host "[1/6] git not found - downloading a source snapshot (later updates will re-download, not `git pull`)." -ForegroundColor Yellow
}
$RepoZip = Join-Path $env:TEMP "itda_source.zip"
Invoke-WebRequest -Uri $RepoZipUrl -OutFile $RepoZip
$Extract = Join-Path $env:TEMP "itda_source_extract"
if (Test-Path $Extract) { Remove-Item $Extract -Recurse -Force }
Expand-Archive -Path $RepoZip -DestinationPath $Extract -Force
$SrcRoot = Get-ChildItem $Extract -Directory | Select-Object -First 1
Copy-Item (Join-Path $SrcRoot.FullName "*") $InstallPath -Recurse -Force
Remove-Item $RepoZip -Force
Remove-Item $Extract -Recurse -Force
}
# Drop dev-only cruft that may have been sitting in the source tree.
Get-ChildItem $InstallPath -Recurse -Directory -Filter "__pycache__" -ErrorAction SilentlyContinue |
Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
# ---------------------------------------------------------------------------
$PyDir = Join-Path $InstallPath "python_embeded"
$PyExe = Join-Path $PyDir "python.exe"
if (-not (Test-Path $PyExe)) {
Write-Host "[2/6] Downloading Python 3.11 (embeddable)..." -ForegroundColor Cyan
$PyZipUrl = "https://www.python.org/ftp/python/3.11.9/python-3.11.9-embed-amd64.zip"
$PyZip = Join-Path $env:TEMP "itda_python_embed.zip"
Invoke-WebRequest -Uri $PyZipUrl -OutFile $PyZip
Expand-Archive -Path $PyZip -DestinationPath $PyDir -Force
Remove-Item $PyZip -Force
# Embeddable Python ships with site-packages import disabled (the ._pth
# file's "import site" line is commented out) - without re-enabling it,
# pip-installed packages are invisible to the interpreter.
$PthFile = Get-ChildItem $PyDir -Filter "python*._pth" | Select-Object -First 1
if ($PthFile) {
(Get-Content $PthFile.FullName) -replace '^#\s*import site', 'import site' | Set-Content $PthFile.FullName
}
Write-Host " Bootstrapping pip..."
$GetPip = Join-Path $env:TEMP "itda_get-pip.py"
Invoke-WebRequest -Uri "https://bootstrap.pypa.io/get-pip.py" -OutFile $GetPip
& $PyExe $GetPip --no-warn-script-location | Out-Null
Remove-Item $GetPip -Force
} else {
Write-Host "[2/6] Python embeddable already present, skipping." -ForegroundColor DarkGray
}
# ---------------------------------------------------------------------------
Write-Host "[3/6] Installing Python dependencies (aiohttp, numpy, opencv, fonttools, librosa)..." -ForegroundColor Cyan
& $PyExe -m pip install --no-warn-script-location --quiet `
aiohttp numpy opencv-python-headless fonttools librosa
# ---------------------------------------------------------------------------
$FfmpegDir = Join-Path $InstallPath "ffmpeg"
$FfmpegExe = Join-Path $FfmpegDir "ffmpeg.exe"
if (-not (Test-Path $FfmpegExe)) {
Write-Host "[4/6] Downloading ffmpeg (BtbN static build)..." -ForegroundColor Cyan
$FfmpegUrl = "https://github.com/BtbN/FFmpeg-Builds/releases/latest/download/ffmpeg-master-latest-win64-gpl.zip"
$FfmpegZip = Join-Path $env:TEMP "itda_ffmpeg.zip"
Invoke-WebRequest -Uri $FfmpegUrl -OutFile $FfmpegZip
$FfmpegExtract = Join-Path $env:TEMP "itda_ffmpeg_extract"
if (Test-Path $FfmpegExtract) { Remove-Item $FfmpegExtract -Recurse -Force }
Expand-Archive -Path $FfmpegZip -DestinationPath $FfmpegExtract -Force
New-Item -ItemType Directory -Force -Path $FfmpegDir | Out-Null
$BinDir = Get-ChildItem $FfmpegExtract -Recurse -Directory -Filter "bin" | Select-Object -First 1
Copy-Item (Join-Path $BinDir.FullName "ffmpeg.exe") $FfmpegDir -Force
Copy-Item (Join-Path $BinDir.FullName "ffprobe.exe") $FfmpegDir -Force
Remove-Item $FfmpegZip -Force
Remove-Item $FfmpegExtract -Recurse -Force
} else {
Write-Host "[4/6] ffmpeg already present, skipping." -ForegroundColor DarkGray
}
# ---------------------------------------------------------------------------
Write-Host "[5/6] Writing launcher..." -ForegroundColor Cyan
$RunBat = Join-Path $InstallPath "Run ITDA.bat"
@"
@echo off
cd /d "%~dp0"
set PATH=%~dp0ffmpeg;%PATH%
"%~dp0python_embeded\python.exe" "%~dp0itda_standalone.py"
pause
"@ | Set-Content -Path $RunBat -Encoding ASCII
# ---------------------------------------------------------------------------
Write-Host "[6/6] Creating desktop shortcut..." -ForegroundColor Cyan
try {
$DesktopPath = [Environment]::GetFolderPath('Desktop')
$WshShell = New-Object -ComObject WScript.Shell
$Shortcut = $WshShell.CreateShortcut((Join-Path $DesktopPath "ITDA.lnk"))
$Shortcut.TargetPath = $RunBat
$Shortcut.WorkingDirectory = $InstallPath
$Shortcut.Description = "ITDA - Frame-Accurate AI Video Stitching (Standalone)"
$Shortcut.Save()
Write-Host " Desktop shortcut created: ITDA.lnk"
} catch {
Write-Host " Couldn't create a desktop shortcut ($($_.Exception.Message)) - use `"$RunBat`" directly." -ForegroundColor Yellow
}
Write-Host ""
Write-Host "=== Done ===" -ForegroundColor Green
Write-Host "Installed to: $InstallPath"
Write-Host "Launch it from the ITDA desktop shortcut, or by running:"
Write-Host " `"$RunBat`""
Write-Host ""