영상 중복 탐지 완성 + 간단 편집(회전·자르기) + 동시 재생 + 별점·태그 세트
중복 탐지 - 이미지 근접쌍 밴드 색인 + 스트리밍 클러스터, 후보 검증(타일 다수결·크롭 해시) - 색 지문으로 색만 다른 오탐 제거, 회전·반전본 탐지(8변형 질의, 선택 옵션) - 오디오 지문(chromaprint)을 같은 디코드 패스에서 뽑아 레터박스 사본을 잡는다. 배경음만 같은 남남은 시각 확인 패스(트림 축 프레임 거리)로 걸러낸다 — 실측 9 vs 29. - 비교 재생(CompareView): 여러 사본을 offset 정렬해 나란히 재생 - 지문 생성 속도 조절(느림·보통·빠름) — 재시작 없이 반영 간단 편집 (원본을 직접 고침, Ctrl+Z로 되돌림) - 회전·반전: JPEG은 EXIF 방향 태그 2바이트만, MP4는 회전 행렬만 — 화질 손실 0. 방향값 전이표는 군의 성질(90도x4=제자리)로 검산하고, 실제 화소를 transpose=1과 비교해 "시계 방향"이 정말 시계인지 확인한다. - 자르기: 화면 좌표 기준(회전 메타가 붙어 있어도 어긋나지 않는다) - 구간 자르기: 스트림 복사라 무손실. 필름스트립 타임라인 + 손잡이 끌기 + 구간 미리보기. - 되돌릴 수 없는 편집(자르기·반전)은 원본을 .archive_trash/edits로 옮겨 보관 - 편집이 수정시각을 바꾸지 않는다 — 기본 정렬이 촬영일이라 항목이 튀면 다시 찾아야 한다 동시 재생 - 고른 영상을 최대 9개 격자에 놓고 함께 재생. 소리는 한 칸만. - 실시간 변환이 필요한 코덱은 2개까지만 — 그 이상은 ffmpeg가 기계를 멈춘다 그 외 - 별점(스냅샷 flags 남는 비트에 얹어 항목당 바이트 증가 0) - 태그: 검색 없이 클릭으로 붙이기, 세트+단축키, 이름 수정 시 붙은 항목에 전파 - 파일 로깅(tracing-appender) — 릴리스는 콘솔이 없어 stdout만으로는 원인을 못 찾았다 - ARM64 크로스 컴파일 스크립트(관리자 권한 없이 VS 카탈로그에서 조립) - DB 마이그레이션 v7~v10 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
67d2ddc59e
commit
8aa74c1a8d
@@ -1,5 +1,6 @@
|
||||
# WebView2 CDP (Chrome DevTools Protocol) E2E helper.
|
||||
# Usage: . .\scripts\cdp.ps1; Invoke-Cdp "document.title"
|
||||
# . .\scripts\cdp.ps1; Save-CdpScreenshot shot.png
|
||||
# Prereq: app launched with WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS=--remote-debugging-port=9223
|
||||
# NOTE: ASCII only in this file (PS 5.1 reads BOM-less files as ANSI).
|
||||
|
||||
@@ -51,3 +52,58 @@ function Invoke-Cdp {
|
||||
}
|
||||
return $response.result.result.value
|
||||
}
|
||||
|
||||
# Call any CDP method and return the raw result object.
|
||||
# Invoke-Cdp is hardcoded to Runtime.evaluate; use this for Page.*, Emulation.*, etc.
|
||||
function Invoke-CdpMethod {
|
||||
param(
|
||||
[Parameter(Mandatory)] [string]$Method,
|
||||
[hashtable]$Params = @{},
|
||||
[int]$Port = 9223,
|
||||
[int]$TimeoutSec = 30
|
||||
)
|
||||
$targets = Invoke-RestMethod "http://127.0.0.1:$Port/json"
|
||||
$page = $targets | Where-Object { $_.type -eq 'page' -and $_.url -notlike 'devtools*' } | Select-Object -First 1
|
||||
if (-not $page) { throw "no CDP page target" }
|
||||
|
||||
$ws = New-Object System.Net.WebSockets.ClientWebSocket
|
||||
$ct = [System.Threading.CancellationToken]::None
|
||||
$ws.ConnectAsync([Uri]$page.webSocketDebuggerUrl, $ct).GetAwaiter().GetResult() | Out-Null
|
||||
|
||||
$msg = @{ id = 1; method = $Method; params = $Params } | ConvertTo-Json -Depth 6 -Compress
|
||||
$bytes = [System.Text.Encoding]::UTF8.GetBytes($msg)
|
||||
$seg = New-Object System.ArraySegment[byte] -ArgumentList @(, $bytes)
|
||||
$ws.SendAsync($seg, [System.Net.WebSockets.WebSocketMessageType]::Text, $true, $ct).GetAwaiter().GetResult() | Out-Null
|
||||
|
||||
# Screenshots are large: keep reading frames until EndOfMessage, then match the id.
|
||||
$buffer = New-Object byte[] 1048576
|
||||
$deadline = (Get-Date).AddSeconds($TimeoutSec)
|
||||
$response = $null
|
||||
while ((Get-Date) -lt $deadline) {
|
||||
$sb = New-Object System.Text.StringBuilder
|
||||
do {
|
||||
$rseg = New-Object System.ArraySegment[byte] -ArgumentList @(, $buffer)
|
||||
$result = $ws.ReceiveAsync($rseg, $ct).GetAwaiter().GetResult()
|
||||
$sb.Append([System.Text.Encoding]::UTF8.GetString($buffer, 0, $result.Count)) | Out-Null
|
||||
} while (-not $result.EndOfMessage)
|
||||
$obj = $sb.ToString() | ConvertFrom-Json
|
||||
if ($obj.id -eq 1) { $response = $obj; break }
|
||||
}
|
||||
$ws.Abort()
|
||||
if (-not $response) { throw "CDP response timeout" }
|
||||
if ($response.error) { throw "CDP error: $($response.error.message)" }
|
||||
return $response.result
|
||||
}
|
||||
|
||||
# Save the page as a PNG (what the WebView actually renders, not the OS window).
|
||||
function Save-CdpScreenshot {
|
||||
param(
|
||||
[Parameter(Mandatory)] [string]$Path,
|
||||
[int]$Port = 9223,
|
||||
[int]$TimeoutSec = 30
|
||||
)
|
||||
$r = Invoke-CdpMethod -Method "Page.captureScreenshot" -Params @{ format = "png" } -Port $Port -TimeoutSec $TimeoutSec
|
||||
if (-not $r.data) { throw "no screenshot data" }
|
||||
[System.IO.File]::WriteAllBytes($Path, [System.Convert]::FromBase64String($r.data))
|
||||
return (Get-Item $Path).Length
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user