summaryrefslogtreecommitdiff
path: root/ar/.config/mpv
diff options
context:
space:
mode:
authorTheSiahxyz <164138827+TheSiahxyz@users.noreply.github.com>2026-06-20 11:10:36 +0900
committerTheSiahxyz <164138827+TheSiahxyz@users.noreply.github.com>2026-06-20 11:10:36 +0900
commitf2a60d11af0b1db24de65a3001afd5019b5259e7 (patch)
treeea394a740f62997d9ed8f3aed44ebef7417df238 /ar/.config/mpv
parentf533c8e39c06c268c4ec68ce47907888181766b4 (diff)
modified mpv/input.conf, modified scripts/integrity-check.lua, created bin/rmev
Diffstat (limited to 'ar/.config/mpv')
-rw-r--r--ar/.config/mpv/input.conf1
-rw-r--r--ar/.config/mpv/scripts/integrity-check.lua179
2 files changed, 166 insertions, 14 deletions
diff --git a/ar/.config/mpv/input.conf b/ar/.config/mpv/input.conf
index 4d63c44..427581f 100644
--- a/ar/.config/mpv/input.conf
+++ b/ar/.config/mpv/input.conf
@@ -71,6 +71,7 @@ alt+h script-message cycle_video_rotate -90
alt+l script-message cycle_video_rotate 90 # Rotate 90
g script-message contact-sheet-close; script-message playlist-view-toggle # Toggle gallery
i script-message-to misc print-media-info # Toggle video info
+I script-message integrity-status # Show integrity check status (playlist)
n set volume 50 # Set volume 50
shift+n set speed 1.0 # Set normal speed 1.0
m cycle mute # Toggle mute
diff --git a/ar/.config/mpv/scripts/integrity-check.lua b/ar/.config/mpv/scripts/integrity-check.lua
index 8db71fa..fce3d1d 100644
--- a/ar/.config/mpv/scripts/integrity-check.lua
+++ b/ar/.config/mpv/scripts/integrity-check.lua
@@ -7,6 +7,11 @@
-- * 손상 구간을 만나면 -xerror 로 즉시 중단 → 손상 파일은 빠르게 판정.
-- * 결과는 경로+수정시각으로 캐시 → 다음에 같은 파일은 즉시 표시.
-- * 손상 파일 경로는 corrupted.log 에 기록.
+-- * 재생목록이 있으면(scan_playlist) 현재 파일 검사가 끝난 뒤,
+-- 뒤따르는 항목들을 한 번에 하나씩 백그라운드로 미리 검사한다.
+-- (배지는 현재 재생 파일에만 표시하고, 미리 검사는 캐시·로그만 갱신)
+-- * 재생목록 미리 검사가 끝나면 OSD 로 요약 알림(notify_done).
+-- script-message integrity-status 로 진행 현황을 즉시 확인할 수 있다.
--
-- 한계: -c copy(디코딩 안 함) 기반이라 컨테이너/끊김/잘림은 잡지만,
-- 컨테이너는 멀쩡하고 화면만 미세하게 깨지는 결함은 못 잡는다.
@@ -22,6 +27,8 @@ local msg = require 'mp.msg'
local opts = {
enabled = true, -- 기능 on/off
scan_on_load = true, -- 파일 열 때 자동 검사
+ scan_playlist = true, -- 현재 파일 검사 후 뒤따르는 재생목록 항목도 백그라운드 검사
+ notify_done = true, -- 재생목록 백그라운드 검사가 끝나면 OSD 로 요약 표시
show_scanning = false, -- 검사 중 표시 여부 (기본: 표시 안 함)
deep_scan = false, -- true 면 디코딩까지 검사(정밀하지만 느림)
use_cache = true, -- 검사 결과 캐시 사용
@@ -45,6 +52,7 @@ local cache = {} -- path -> {mtime=, size=, status=, errors=}
local overlay = mp.create_osd_overlay("ass-events")
local current_path = nil
local scan_token = 0 -- 오래된(stale) 콜백 무시용
+local bg_token = 0 -- 재생목록 백그라운드 검사 무효화용
----------------------------------------------------------------------
-- 캐시 입출력
@@ -173,7 +181,25 @@ local function apply_result(path, corrupt, from_cache)
if not from_cache then append_cache(path, cache[path]) end
end
-local function start_scan(path)
+-- subprocess 결과를 손상 여부로 환산
+local function determine_corrupt(result)
+ local stderr = result.stderr or ""
+ local status = result.status or 0
+ return (stderr:gsub("%s+", "") ~= "") or (status ~= 0)
+end
+
+-- 캐시가 현재 파일 상태(수정시각·크기)와 일치하면 그 항목을 반환
+local function cached_fresh(path)
+ if not (opts.use_cache and cache[path]) then return nil end
+ local mtime, size = file_sig(path)
+ local e = cache[path]
+ if mtime and e.mtime == mtime and e.size == size then
+ return e
+ end
+ return nil
+end
+
+local function start_scan(path, on_done)
scan_token = scan_token + 1
local token = scan_token
show_scanning()
@@ -192,32 +218,140 @@ local function start_scan(path)
hide_badge()
return
end
- local stderr = result.stderr or ""
- local status = result.status or 0
- local corrupt = (stderr:gsub("%s+", "") ~= "") or (status ~= 0)
- apply_result(path, corrupt, false)
+ apply_result(path, determine_corrupt(result), false)
+ if on_done then on_done() end
end)
end
----------------------------------------------------------------------
+-- 재생목록 백그라운드 검사 (현재 파일 검사 완료 후 뒤따르는 항목들)
+----------------------------------------------------------------------
+-- 진행 중인 재생목록 검사를 무효화(파일 전환·토글 시)
+local function cancel_bg()
+ bg_token = bg_token + 1
+end
+
+-- 재생목록 항목의 filename 을 실제 검사 가능한 경로로 변환
+local function resolve_playlist_path(filename)
+ if not filename then return nil end
+ if filename:find("^%a[%w%+%-%.]*://") then return filename end -- URL 은 그대로
+ if filename:find("^/") then return filename end -- 절대경로
+ local wd = mp.get_property("working-directory")
+ if wd then return utils.join_path(wd, filename) end
+ return filename
+end
+
+-- 배지 없이 캐시·로그만 갱신 (백그라운드 항목용)
+local function record_result_quiet(path, corrupt)
+ local mtime, size = file_sig(path)
+ cache[path] = {
+ mtime = mtime or 0,
+ size = size or 0,
+ status = corrupt and "corrupt" or "ok",
+ errors = 0,
+ }
+ if corrupt then
+ log_corrupted(path)
+ msg.warn("손상됨(재생목록): " .. path)
+ end
+ append_cache(path, cache[path])
+end
+
+-- 재생목록 전체의 검사 현황을 캐시 기준으로 집계
+local function playlist_stats()
+ local count = mp.get_property_number("playlist-count", 0)
+ local s = { total = 0, ok = 0, corrupt = 0, pending = 0 }
+ for i = 0, count - 1 do
+ local path = resolve_playlist_path(
+ mp.get_property("playlist/" .. i .. "/filename"))
+ if scannable(path) then
+ s.total = s.total + 1
+ local e = cached_fresh(path)
+ if not e then s.pending = s.pending + 1
+ elseif e.status == "corrupt" then s.corrupt = s.corrupt + 1
+ else s.ok = s.ok + 1 end
+ end
+ end
+ return s
+end
+
+-- start_index 부터 재생목록 끝까지 한 번에 하나씩 순차 검사
+local function scan_playlist_from(start_index)
+ cancel_bg()
+ local token = bg_token
+ local count = mp.get_property_number("playlist-count", 0)
+ local did_scan = false -- 이번 검사에서 실제로 새로 검사한 항목이 있었는지
+
+ -- 끝까지 도달했을 때 요약 알림(새로 검사한 게 있을 때만 — 자동재생 중복 방지)
+ local function finish()
+ if not (opts.notify_done and did_scan) then return end
+ local s = playlist_stats()
+ local txt = (s.corrupt > 0)
+ and string.format("재생목록 검사 완료 · 손상 %d개 (총 %d)", s.corrupt, s.total)
+ or string.format("재생목록 검사 완료 · 이상 없음 (총 %d)", s.total)
+ mp.osd_message(txt, 4)
+ msg.info(txt)
+ end
+
+ local function step(i)
+ if token ~= bg_token then return end -- 파일 전환/토글 → 중단
+ if i >= count then finish(); return end
+ local path = resolve_playlist_path(
+ mp.get_property("playlist/" .. i .. "/filename"))
+ if not scannable(path) then return step(i + 1) end
+ if path == current_path then return step(i + 1) end -- 현재 파일은 이미 검사됨
+ if cached_fresh(path) then return step(i + 1) end -- 이미 검사된 파일은 건너뜀
+
+ did_scan = true
+ mp.command_native_async({
+ name = "subprocess",
+ args = build_args(path),
+ playback_only = false,
+ capture_stdout = true,
+ capture_stderr = true,
+ }, function(success, result, err)
+ if token ~= bg_token then return end -- 중간에 무효화됨 → 무시
+ if result and not result.killed_by_us
+ and result.error_string ~= "init" then
+ record_result_quiet(path, determine_corrupt(result))
+ end
+ step(i + 1)
+ end)
+ end
+
+ step(start_index)
+end
+
+-- 재생목록이 있으면 현재 위치 다음 항목부터 백그라운드 검사 시작
+local function maybe_scan_playlist()
+ if not (opts.enabled and opts.scan_playlist) then return end
+ local count = mp.get_property_number("playlist-count", 0)
+ if count <= 1 then return end -- 재생목록 없음
+ local pos = mp.get_property_number("playlist-pos", 0)
+ scan_playlist_from(pos + 1)
+end
+
+----------------------------------------------------------------------
-- 이벤트
----------------------------------------------------------------------
local function on_file_loaded()
hide_badge()
+ cancel_bg() -- 이전 재생목록 검사 중단
current_path = mp.get_property("path")
if not opts.enabled or not opts.scan_on_load then return end
- if not scannable(current_path) then return end
+ if not scannable(current_path) then
+ maybe_scan_playlist() -- 현재가 스트림이어도 목록은 검사
+ return
+ end
-- 캐시 적중(수정시각·크기 동일)이면 즉시 표시
- if opts.use_cache and cache[current_path] then
- local mtime, size = file_sig(current_path)
- local e = cache[current_path]
- if mtime and e.mtime == mtime and e.size == size then
- apply_result(current_path, e.status == "corrupt", true)
- return
- end
+ local e = cached_fresh(current_path)
+ if e then
+ apply_result(current_path, e.status == "corrupt", true)
+ maybe_scan_playlist()
+ return
end
- start_scan(current_path)
+ start_scan(current_path, maybe_scan_playlist) -- 현재 검사 완료 후 목록 검사
end
----------------------------------------------------------------------
@@ -236,6 +370,7 @@ end
local function toggle()
opts.enabled = not opts.enabled
if not opts.enabled then
+ cancel_bg()
hide_badge()
else
on_file_loaded()
@@ -243,10 +378,26 @@ local function toggle()
mp.osd_message("무결성 검사: " .. (opts.enabled and "켜짐" or "꺼짐"))
end
+-- 재생목록 검사 현황을 즉시 표시 (끝났는지 / 얼마나 남았는지 확인용)
+local function status()
+ local count = mp.get_property_number("playlist-count", 0)
+ if count <= 1 then
+ mp.osd_message("무결성: 재생목록 없음")
+ return
+ end
+ local s = playlist_stats()
+ local state = (s.pending == 0) and "검사 완료" or ("검사 중(남음 " .. s.pending .. ")")
+ mp.osd_message(string.format(
+ "무결성 %s · 정상 %d · 손상 %d · 미검사 %d (총 %d)",
+ state, s.ok, s.corrupt, s.pending, s.total), 4)
+end
+
mp.add_key_binding(nil, "rescan", rescan)
mp.add_key_binding(nil, "toggle", toggle)
+mp.add_key_binding(nil, "status", status)
mp.register_script_message("integrity-rescan", rescan)
mp.register_script_message("integrity-toggle", toggle)
+mp.register_script_message("integrity-status", status)
----------------------------------------------------------------------
-- 초기화