Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 40 additions & 1 deletion src/ffmpeg.lisp
Original file line number Diff line number Diff line change
@@ -1,6 +1,39 @@
(in-package :visp)

(defun validate-output-path (output)
"Validate output path before ffmpeg execution"
(let* ((output-pathname (pathname output))
(output-dir (uiop:pathname-directory-pathname output-pathname)))
;; ディレクトリ存在確認
;; 相対パスの場合はカレントディレクトリからの解決を行う
(unless (uiop:directory-exists-p output-dir)
(format t "~a Output directory does not exist: ~a~%"
(log-tag "error") (namestring output-dir))
(uiop:quit 1))

;; 出力ファイル名の基本チェック
(let ((filename (file-namestring output-pathname)))
(when (string= filename "")
(format t "~a Invalid output filename: ~a~%"
(log-tag "error") output)
(uiop:quit 1)))))

(defun cleanup-partial-output (output)
"Clean up partially created output file if it exists and is empty/corrupted"
(when (probe-file output)
(let ((file-size (with-open-file (stream output :direction :input
:if-does-not-exist nil)
(when stream (file-length stream)))))
;; 0バイトまたは非常に小さいファイル(ヘッダーのみ等)は削除
(when (and file-size (< file-size 1024))
(delete-file output)
(format t "~a Cleaned up incomplete output file: ~a~%"
(log-tag "info") output)))))

(defun run-cmd (cmd output dry-run)
;; Phase 1: 事前検証
(validate-output-path output)

(when (probe-file output)
(format t "~a Output file '~a' already exists. It will be overwritten.~%"
(log-tag "warn") output))
Expand All @@ -11,7 +44,13 @@
(format t "~a Command: ~{~a ~}~%" (log-tag "dry-run") cmd))
(progn
(format t "~a Running: ~{~a ~}~%" (log-tag "info") cmd)
(uiop:run-program cmd :output t :error-output t))))
;; Phase 1: 実行前後でのクリーンアップ対応準備
(handler-case
(uiop:run-program cmd :output t :error-output t)
(error (e)
;; 簡易的なエラー処理(Phase 2で本格化)
(cleanup-partial-output output)
(error e))))))

(defun build-gif-cmd (opts output fps)
"Construct the ffmpeg command list for GIF mode using input filename and target fps."
Expand Down
2 changes: 2 additions & 0 deletions src/package.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@
:build-cmd
:encoder-available-p
:ffmpeg-available-p
:validate-output-path
:cleanup-partial-output

;; log.lisp
:log-tag
Expand Down
45 changes: 43 additions & 2 deletions t/test-ffmpeg.lisp
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
(defpackage :visp.test.ffmpeg
(:use :cl :rove)
(:import-from :visp
:make-visp-options))
:make-visp-options
:validate-output-path
:cleanup-partial-output))

(in-package :visp.test.ffmpeg)

Expand Down Expand Up @@ -100,4 +102,43 @@
(ok (equal (visp:build-cmd opts output)
'("ffmpeg" "-y" "-i" "input.mp4"
"-vf" "scale=1920:1080,setpts=PTS/0.5,hflip"
"complex-speed.mp4"))))))
"complex-speed.mp4"))))))

(deftest validate-output-path-tests
(testing "Validates existing directory paths"
;; カレントディレクトリは存在するはず
(ok (not (signals error (validate-output-path "test-output.mp4"))))
(ok (not (signals error (validate-output-path "./test-output.mp4")))))

;; NOTE: uiop:quitを呼ぶ関数のテストは現在のテストフレームワークでは困難
;; 実際のエラーケースのテストは統合テストで実行する
)

(deftest cleanup-partial-output-tests
(testing "Cleans up small/empty files"
;; 小さなテストファイルを作成
(let ((test-file "test-partial.mp4"))
;; 空ファイルを作成
(with-open-file (stream test-file :direction :output
:if-exists :supersede)
(write-string "" stream))

;; クリーンアップが動作することを確認
(ok (probe-file test-file))
(cleanup-partial-output test-file)
(ok (not (probe-file test-file)))))

(testing "Preserves normal-sized files"
;; 通常サイズのファイルは削除されない
(let ((test-file "test-normal.mp4"))
;; 十分なサイズのファイルを作成
(with-open-file (stream test-file :direction :output
:if-exists :supersede)
(write-string (make-string 2048 :initial-element #\a) stream))

(ok (probe-file test-file))
(cleanup-partial-output test-file)
(ok (probe-file test-file))

;; テスト後のクリーンアップ
(delete-file test-file))))
2 changes: 1 addition & 1 deletion t/test-util.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
(deftest parse-frame-rate-tests
(testing "Parses valid frame rate strings"
(ok (= (visp:parse-frame-rate "30") 30.0))
(ok (= (visp:parse-frame-rate "30000/1001") (/ 30000.0 1001))))
(ok (= (visp:parse-frame-rate "30000/1001") (/ 30000 1001))))

(testing "Handles invalid input gracefully"
(ok (null (visp:parse-frame-rate "not-a-number")))
Expand Down