From 4c5a1f2f09f6906bf26a783d2fa345a5886a2335 Mon Sep 17 00:00:00 2001
From: wangzhibo <wangzhibo@shsening.com>
Date: 星期三, 04 十二月 2024 09:49:30 +0800
Subject: [PATCH] modified split using cv2
---
__pycache__/cv2.cpython-310.pyc | 0
test/t_ffmpeg.py | 3
test/pipe_test.py | 60 +
pipe_sample.txt | 1
test/pygame_test.py | 107 ++
test/sence_detect_demo.py | 70 +
test/tk.py | 77 +
video-splitor.py | 694 +++++++++++++++++
videosplitorV0.1.spec | 42
test/refresh.py | 24
test/pi.py | 70 +
README.md | 26
VLC.zip | 0
/dev/null | 467 -----------
test/pipe_test copy.py | 71 +
test/ffmpeg_read_cv2_write.py | 74 +
cv2_player.py | 114 ++
test/scene_detect_demo.py | 69 +
test/t_ssim.py | 66 +
test/ffplay_test.py | 94 ++
test/vlc_test.py | 106 ++
test/loop.py | 33
test/test_cv.py | 94 ++
23 files changed, 1,866 insertions(+), 496 deletions(-)
diff --git a/README.md b/README.md
index 490c1c2..8b33d20 100644
--- a/README.md
+++ b/README.md
@@ -21,4 +21,28 @@
鎵撳寘 exe
-1銆乸yinstaller videosplitorV0.1.spec
\ No newline at end of file
+1銆乸yinstaller videosplitorV0.1.spec
+
+
+
+
+PS. 娣诲姞鏈湴鏂囦欢澶瑰埌杩滅▼ git server锛�
+
+1. 鍒濆鍖栨湰鍦� Git 浠撳簱
+cd /path/to/your/folder
+git init
+
+2. 娣诲姞鏂囦欢鍒� Git 浠撳簱
+git add .
+
+3. 鎻愪氦鏂囦欢鍒版湰鍦� Git 浠撳簱
+git commit -m "Initial commit"
+
+4. 杩炴帴鍒拌繙绋� Git 浠撳簱
+git remote add origin ssh://wangzhibo@192.168.0.75:29418/Python_Video_Splitor.git
+
+5. 鎺ㄩ�佹湰鍦颁唬鐮佸埌杩滅▼浠撳簱
+git push -u origin master
+
+6. 楠岃瘉鎺ㄩ�佺粨鏋�
+git remote -v
diff --git a/VLC.zip b/VLC.zip
new file mode 100644
index 0000000..d1978eb
--- /dev/null
+++ b/VLC.zip
Binary files differ
diff --git a/__pycache__/cv2.cpython-310.pyc b/__pycache__/cv2.cpython-310.pyc
new file mode 100644
index 0000000..b2b9eff
--- /dev/null
+++ b/__pycache__/cv2.cpython-310.pyc
Binary files differ
diff --git a/build.bat b/build.bat
deleted file mode 100644
index 646ce91..0000000
--- a/build.bat
+++ /dev/null
@@ -1 +0,0 @@
-pyinstaller --name=瑙嗛鍒嗘V0.1 --clean --onefile -y tkv.py --icon ./main.ico
\ No newline at end of file
diff --git a/cv2_player.py b/cv2_player.py
new file mode 100644
index 0000000..a74fdee
--- /dev/null
+++ b/cv2_player.py
@@ -0,0 +1,114 @@
+import cv2
+import tkinter as tk
+from tkinter import filedialog, ttk
+from PIL import Image, ImageTk
+
+
+class VideoPlayer:
+ def __init__(self, root):
+ self.root = root
+ self.root.title("Tkinter MP4 鎾斁鍣�")
+
+ # 瑙嗛鎺т欢
+ self.video_label = tk.Label(root)
+ self.video_label.pack()
+
+ # 鎸夐挳鍜岃繘搴︽潯鍖哄煙
+ controls_frame = tk.Frame(root)
+ controls_frame.pack()
+
+ self.play_button = tk.Button(controls_frame, text="鎾斁", command=self.toggle_play_pause)
+ self.play_button.grid(row=0, column=0, padx=5)
+
+ self.replay_button = tk.Button(controls_frame, text="閲嶆柊鎾斁", command=self.replay_video)
+ self.replay_button.grid(row=0, column=1, padx=5)
+
+ self.progress = ttk.Scale(controls_frame, from_=0, to=1, orient="horizontal", command=self.seek_video)
+ self.progress.grid(row=0, column=2, padx=5, sticky="ew")
+
+ controls_frame.columnconfigure(2, weight=1)
+
+ # 鐘舵�佸彉閲�
+ self.cap = None
+ self.is_playing = False
+ self.current_frame = 0
+ self.total_frames = 0
+ self.fps = 30
+ self.video_path = None
+
+ # 鏂囦欢鎵撳紑鎸夐挳
+ self.open_button = tk.Button(root, text="鎵撳紑瑙嗛", command=self.open_file)
+ self.open_button.pack()
+
+ def open_file(self):
+ self.video_path = filedialog.askopenfilename(filetypes=[("MP4鏂囦欢", "*.mp4"), ("鎵�鏈夋枃浠�", "*.*")])
+ if not self.video_path:
+ return
+ self.load_video()
+
+ def load_video(self):
+ if self.cap:
+ self.cap.release()
+ self.cap = cv2.VideoCapture(self.video_path)
+ if not self.cap.isOpened():
+ tk.messagebox.showerror("閿欒", "鏃犳硶鎵撳紑瑙嗛")
+ return
+ self.fps = int(self.cap.get(cv2.CAP_PROP_FPS))
+ self.total_frames = int(self.cap.get(cv2.CAP_PROP_FRAME_COUNT))
+ self.current_frame = 0
+ self.progress.config(to=self.total_frames)
+ self.is_playing = True
+ self.play_button.config(text="鏆傚仠")
+ self.play_video()
+
+ def play_video(self):
+ if not self.is_playing or not self.cap:
+ return
+
+ ret, frame = self.cap.read()
+ if ret:
+ self.current_frame += 1
+ self.progress.set(self.current_frame)
+ frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
+ img = ImageTk.PhotoImage(Image.fromarray(frame))
+ self.video_label.config(image=img)
+ self.video_label.image = img
+ self.root.after(int(1000 / self.fps), self.play_video)
+ else:
+ self.is_playing = False
+ self.play_button.config(text="鎾斁")
+
+ def toggle_play_pause(self):
+ if not self.cap:
+ return
+ if self.is_playing:
+ self.is_playing = False
+ self.play_button.config(text="鎾斁")
+ else:
+ self.is_playing = True
+ self.play_button.config(text="鏆傚仠")
+ self.play_video()
+
+ def replay_video(self):
+ if not self.cap:
+ return
+ self.cap.set(cv2.CAP_PROP_POS_FRAMES, 0)
+ self.current_frame = 0
+ self.progress.set(0)
+ self.is_playing = True
+ self.play_button.config(text="鏆傚仠")
+ self.play_video()
+
+ def seek_video(self, value):
+ if not self.cap:
+ return
+ self.current_frame = int(float(value))
+ self.cap.set(cv2.CAP_PROP_POS_FRAMES, self.current_frame)
+ if not self.is_playing:
+ self.play_video()
+
+
+# 鍒涘缓涓荤獥鍙�
+root = tk.Tk()
+app = VideoPlayer(root)
+root.mainloop()
diff --git a/libvlc.dll b/libvlc.dll
deleted file mode 100644
index 8f77033..0000000
--- a/libvlc.dll
+++ /dev/null
Binary files differ
diff --git a/libvlccore.dll b/libvlccore.dll
deleted file mode 100644
index 1f7f1c3..0000000
--- a/libvlccore.dll
+++ /dev/null
Binary files differ
diff --git a/pipe_sample.txt b/pipe_sample.txt
new file mode 100644
index 0000000..24d473f
--- /dev/null
+++ b/pipe_sample.txt
@@ -0,0 +1 @@
+ffmpeg -i demo.mp4 -vf fps=30 -q:v 2 -f image2pipe - | ffmpeg -framerate 30 -f image2pipe -i - -c:v libx264 -preset slow -crf 18 -pix_fmt yuv420p output.mp4
\ No newline at end of file
diff --git a/test/ffmpeg_read_cv2_write.py b/test/ffmpeg_read_cv2_write.py
new file mode 100644
index 0000000..583b00e
--- /dev/null
+++ b/test/ffmpeg_read_cv2_write.py
@@ -0,0 +1,74 @@
+import cv2
+import numpy as np
+import subprocess
+
+def read_video_frames_to_memory(video_path, frame_rate=30):
+ """
+ 浣跨敤 FFmpeg 灏嗚棰戝抚浠� PNG 鏍煎紡鐩存帴璇诲彇鍒板唴瀛樹腑銆�
+ """
+ ffmpeg_command = [
+ "ffmpeg", "-i", video_path,
+ "-vf", f"fps={frame_rate}",
+ "-f", "image2pipe", "-vcodec", "png", "-"
+ ]
+
+ frame_size = 1080*1440*3
+
+ # 浣跨敤 subprocess 鎵撳紑 FFmpeg 杩涚▼
+ process = subprocess.Popen(ffmpeg_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=frame_size**1)
+
+ frames = []
+ try:
+ while True:
+ # 璇诲彇鍗曞抚鏁版嵁
+ frame_bytes = process.stdout.read(frame_size) # 姣忔灏濊瘯璇诲彇 1MB
+ if not frame_bytes:
+ break
+
+ # 瑙g爜 PNG 鏁版嵁涓� NumPy 鏁扮粍锛堜娇鐢� OpenCV锛�
+ frame = cv2.imdecode(np.frombuffer(frame_bytes, np.uint8), cv2.IMREAD_UNCHANGED)
+ if frame is not None:
+ frames.append(frame)
+ finally:
+ process.stdout.close()
+ process.wait()
+
+ return frames
+
+def write_frames_to_mp4(frames, output_path, frame_rate=30):
+ """
+ 浠庡抚鏁版嵁鐢熸垚 MP4 鏂囦欢銆�
+ """
+ if not frames:
+ print("No frames to write.")
+ return
+
+ # 鑾峰彇甯у昂瀵� (楂樺害, 瀹藉害)
+ frame_height, frame_width = frames[0].shape[:2]
+ print(frame_width,frame_height)
+
+ # 瀹氫箟瑙嗛缂栫爜鍣ㄥ拰杈撳嚭鏂囦欢
+ fourcc = cv2.VideoWriter_fourcc(*"mp4v") # MP4 鏍煎紡缂栫爜鍣�
+ video_writer = cv2.VideoWriter(output_path, fourcc, frame_rate, (frame_width, frame_height))
+
+ for frame in frames:
+ # 妫�鏌ュ抚鏄惁鏄笁閫氶亾 (RGB/BGR)锛屽鏋滈渶瑕佽浆鎹㈡牸寮�
+ if len(frame.shape) == 2: # 鐏板害鍥�
+ frame = cv2.cvtColor(frame, cv2.COLOR_GRAY2BGR)
+ elif frame.shape[2] == 4: # RGBA
+ frame = cv2.cvtColor(frame, cv2.COLOR_RGBA2BGR)
+
+ video_writer.write(frame)
+
+ video_writer.release()
+ print(f"Video saved to {output_path}")
+
+if __name__ == "__main__":
+ video_path = "E:/鎶栭煶-AI椋庢櫙/Test/demo.mp4"
+ output_path = "output.mp4"
+
+ # 璇诲彇瑙嗛甯у埌鍐呭瓨
+ frames = read_video_frames_to_memory(video_path)
+
+ # 灏嗗抚鏁版嵁鍐欏叆 MP4 鏂囦欢
+ write_frames_to_mp4(frames, output_path)
diff --git a/test/ffplay_test.py b/test/ffplay_test.py
new file mode 100644
index 0000000..86ab341
--- /dev/null
+++ b/test/ffplay_test.py
@@ -0,0 +1,94 @@
+import subprocess
+import tkinter as tk
+from tkinter import ttk
+import threading
+import time
+
+class VideoPlayer:
+ def __init__(self, root, video_path):
+ self.root = root
+ self.video_path = video_path
+ self.is_paused = False
+ self.is_running = True
+
+ # 鍒涘缓鐣岄潰鍏冪礌
+ self.canvas = tk.Canvas(root, width=640, height=480)
+ self.canvas.pack()
+
+ self.play_button = tk.Button(root, text="鎾斁/鏆傚仠", command=self.toggle_pause)
+ self.play_button.pack(side=tk.LEFT)
+
+ self.restart_button = tk.Button(root, text="閲嶆柊鎾斁", command=self.restart_video)
+ self.restart_button.pack(side=tk.LEFT)
+
+ self.progress = ttk.Scale(root, from_=0, to=100, orient=tk.HORIZONTAL, command=self.update_position)
+ self.progress.pack(fill=tk.X, expand=True)
+
+ # 鍚姩鎾斁瑙嗛绾跨▼
+ self.video_thread = threading.Thread(target=self.play_video)
+ self.video_thread.start()
+
+ def toggle_pause(self):
+ """鍒囨崲鎾斁/鏆傚仠鐘舵��"""
+ if self.is_paused:
+ self.is_paused = False
+ else:
+ self.is_paused = True
+
+ def restart_video(self):
+ """閲嶆柊寮�濮嬫挱鏀�"""
+ self.is_paused = False
+ self.progress.set(0)
+ self.play_video()
+
+ def update_position(self, value):
+ """鏇存柊杩涘害鏉′綅缃�"""
+ self.current_position = float(value)
+
+ def play_video(self):
+ """鎾斁瑙嗛骞舵洿鏂拌繘搴︽潯"""
+ # subprocess.run 浼氶樆濉烇紝鍚姩涓�涓悗鍙拌繘绋嬭繍琛� ffplay
+ ffplay_cmd = ["ffplay", "-i", self.video_path, "-v", "quiet", "-x", "640", "-y", "480", "-autoexit"]
+
+ # 鍒涘缓 subprocess 鏉ユ挱鏀捐棰�
+ process = subprocess.Popen(ffplay_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+
+ while self.is_running:
+ if self.is_paused:
+ continue
+ # 鏇存柊杩涘害鏉�
+ self.update_progress(process)
+ time.sleep(0.1) # 鎺у埗鏇存柊棰戠巼
+
+ process.wait() # 绛夊緟瑙嗛鎾斁缁撴潫
+ self.restart_video() # 鎾斁缁撴潫鍚庤嚜鍔ㄩ噸鎾�
+
+ def update_progress(self, process):
+ """鏇存柊杩涘害鏉�"""
+ # 鑾峰彇 ffplay 鐨勮緭鍑哄苟鏇存柊杩涘害
+ stdout, stderr = process.communicate()
+ lines = stderr.decode().splitlines()
+ for line in lines:
+ if "time=" in line:
+ # 鎻愬彇鏃堕棿淇℃伅
+ current_time = line.split("time=")[-1].split(" ")[0]
+ hours, minutes, seconds = map(float, current_time.split(":"))
+ total_seconds = hours * 3600 + minutes * 60 + seconds
+ video_duration = 120 # 鎵嬪姩璁剧疆瑙嗛鏃堕暱锛屾垨鑰呴�氳繃鍏朵粬鏂瑰紡鑾峰彇鏃堕暱
+ progress_percentage = (total_seconds / video_duration) * 100
+ self.progress.set(progress_percentage)
+
+ def close(self):
+ """鍏抽棴瑙嗛鎾斁鍣�"""
+ self.is_running = False
+ self.video_thread.join()
+
+# 鍒涘缓 Tkinter 绐楀彛
+root = tk.Tk()
+root.title("瑙嗛鎾斁鍣�")
+
+media_path = "E:/鎶栭煶-AI椋庢櫙/data/鍏虫敞/1515593476095344/瑙嗛/7375164244729302272.mp4" # 鏇挎崲涓哄疄闄呰棰戞枃浠惰矾寰�
+player = VideoPlayer(root, media_path)
+
+root.protocol("WM_DELETE_WINDOW", player.close)
+root.mainloop()
diff --git a/test/loop.py b/test/loop.py
new file mode 100644
index 0000000..8199b6c
--- /dev/null
+++ b/test/loop.py
@@ -0,0 +1,33 @@
+import vlc
+from pathlib import Path
+import time
+import os
+
+
+class Loop_Vlc_Player:
+
+ def __init__(self):
+ self.player = vlc.Instance()
+
+ def addPlayList(self, localPath):
+ self.mediaList = self.player.media_list_new()
+ self.mediaList.add_media(localPath)
+ self.listPlayer = self.player.media_list_player_new()
+ self.listPlayer.set_media_list(self.mediaList)
+ self.listPlayer.set_playback_mode(vlc.PlaybackMode(1))
+
+ def play(self):
+ self.listPlayer.play()
+
+ def stop(self):
+ self.listPlayer.stop()
+
+
+play = Loop_Vlc_Player()
+video_path = "E:/鎶栭煶-AI椋庢櫙/data/鍏虫敞/1515593476095344/瑙嗛/7375164244729302272.mp4" # 鏇挎崲涓哄疄闄呰棰戞枃浠惰矾寰�
+
+play.addPlayList(video_path)
+play.play()
+while True:
+ pass
+
diff --git a/test/pi.py b/test/pi.py
new file mode 100644
index 0000000..1fbf48d
--- /dev/null
+++ b/test/pi.py
@@ -0,0 +1,70 @@
+import cv2
+import os
+
+def slice_video_by_frames(video_path, frame_segments, output_dir, codec="mp4v", fps=None):
+ """
+ 浣跨敤 OpenCV 瀹炵幇瑙嗛鎸夊抚鍒囧垎銆�
+
+ 鍙傛暟锛�
+ - video_path: 杈撳叆瑙嗛璺緞銆�
+ - frame_segments: 甯у尯闂寸殑鍒楄〃锛屼緥濡傦細[(start_frame1, end_frame1), (start_frame2, end_frame2), ...]銆�
+ - output_dir: 杈撳嚭鏂囦欢澶硅矾寰勩��
+ - codec: 瑙嗛缂栫爜鍣紝榛樿鏄� "mp4v"锛堥�傚悎鐢熸垚 MP4锛夈��
+ - fps: 甯х巼锛岄粯璁や负杈撳叆瑙嗛鐨勫抚鐜囥��
+ """
+ # 鍒涘缓杈撳嚭鐩綍
+ os.makedirs(output_dir, exist_ok=True)
+
+ # 鎵撳紑瑙嗛
+ video_capture = cv2.VideoCapture(video_path)
+ if not video_capture.isOpened():
+ raise ValueError(f"鏃犳硶鎵撳紑瑙嗛鏂囦欢: {video_path}")
+
+ # 鑾峰彇瑙嗛灞炴��
+ original_fps = video_capture.get(cv2.CAP_PROP_FPS)
+ frame_width = int(video_capture.get(cv2.CAP_PROP_FRAME_WIDTH))
+ frame_height = int(video_capture.get(cv2.CAP_PROP_FRAME_HEIGHT))
+ total_frames = int(video_capture.get(cv2.CAP_PROP_FRAME_COUNT))
+
+ if fps is None:
+ fps = original_fps
+
+ print(f"瑙嗛灞炴�э細鎬诲抚鏁�={total_frames}, 甯х巼={original_fps}, 鍒嗚鲸鐜�={frame_width}x{frame_height}")
+
+ for idx, (start_frame, end_frame) in enumerate(frame_segments):
+ # 鏍¢獙甯ц寖鍥�
+ if start_frame < 0 or end_frame > total_frames or start_frame >= end_frame:
+ print(f"鏃犳晥鐨勫抚鍖洪棿锛�({start_frame}, {end_frame})")
+ continue
+
+ # 杈撳嚭鏂囦欢璺緞
+ output_file = os.path.join(output_dir, f"slice_{idx+1}.mp4")
+
+ # 鍒濆鍖栬棰戝啓鍏ュ櫒
+ fourcc = cv2.VideoWriter_fourcc(*codec)
+ video_writer = cv2.VideoWriter(output_file, fourcc, fps, (frame_width, frame_height))
+
+ # 璺宠浆鍒拌捣濮嬪抚
+ video_capture.set(cv2.CAP_PROP_POS_FRAMES, start_frame)
+
+ # 閫愬抚璇诲彇骞跺啓鍏�
+ for frame_idx in range(start_frame, end_frame):
+ ret, frame = video_capture.read()
+ if not ret:
+ print(f"鏃犳硶璇诲彇甯э細{frame_idx}")
+ break
+ video_writer.write(frame)
+
+ video_writer.release()
+ print(f"鐢熸垚鍒囩墖: {output_file} ({start_frame} ~ {end_frame})")
+
+ video_capture.release()
+ print("瑙嗛鍒囧垎瀹屾垚銆�")
+
+# 绀轰緥鐢ㄦ硶
+if __name__ == "__main__":
+ video_path = "E:/鎶栭煶-AI椋庢櫙/Test/demo.mp4" # 鏇挎崲涓轰綘鐨勮緭鍏ヨ棰戣矾寰�
+ output_dir = "output" # 鏇挎崲涓轰綘鐨勮緭鍑烘枃浠跺す璺緞
+ frame_segments = [(0, 60),(60, 79), (79,98),(98,116), (116,135),(135, 153), (153,172), (172,190), (190,209), (209,228), (228,247), (247,266), (266,285),(285,305)] # 瀹氫箟甯у尯闂�
+
+ slice_video_by_frames(video_path, frame_segments, output_dir)
\ No newline at end of file
diff --git a/test/pipe_test copy.py b/test/pipe_test copy.py
new file mode 100644
index 0000000..5495ca6
--- /dev/null
+++ b/test/pipe_test copy.py
@@ -0,0 +1,71 @@
+import subprocess
+import os
+
+def split_video_by_pipe(video_path, frame_segments, width, height, output_dir):
+ """
+ 浣跨敤 FFmpeg 鐨勭閬撴柟寮忥紝灏嗚棰戞媶鍒嗘垚鎸囧畾鐨勫抚鍒囩墖锛岃緭鍑轰负澶氫釜瑙嗛鏂囦欢銆�
+
+ 鍙傛暟锛�
+ - video_path: 杈撳叆瑙嗛璺緞
+ - frame_segments: 鍒囩墖甯ф锛屼緥濡傦細[0, M1, M2, ..., Mlast]
+ - width, height: 瑙嗛鍒嗚鲸鐜囷紝鐢ㄤ簬璁$畻甯уぇ灏�
+ - output_dir: 杈撳嚭鏂囦欢鐩綍
+ """
+ # 瑙嗛甯ф牸寮忓亣璁� RGB锛堟瘡鍍忕礌 3 瀛楄妭锛�
+ bytes_per_pixel = 3
+ frame_size = width * height * bytes_per_pixel # 鍗曞抚鐨勫瓧鑺傚ぇ灏�
+
+ # 鍒涘缓杈撳嚭瀛愮洰褰�
+ os.makedirs(output_dir, exist_ok=True)
+
+ # 鎵撳紑瑙嗛瑙g爜绠¢亾锛岀敤浜庡抚鎻愬彇
+ ffmpeg_extract = [
+ "ffmpeg", "-i", video_path, "-vf", "fps=30", "-f", "image2pipe", "-vcodec", "rawvideo", "-"
+ ]
+ process_extract = subprocess.Popen(ffmpeg_extract, stdout=subprocess.PIPE, bufsize=frame_size * 1)
+
+ # 鍒涘缓澶氫釜甯у垎娈电閬�
+ slice_pipes = []
+ for i, _ in enumerate(frame_segments[:-1]):
+ output_file = os.path.join(output_dir, f"slice_{i+1}.mp4")
+ ffmpeg_encode = [
+ "ffmpeg", "-framerate", "30", "-f", "rawvideo", "-vcodec", "rawvideo", "-s", f"{width}x{height}", "-pix_fmt", "rgb24", "-i", "-",
+ "-c:v", "libx264", "-preset", "slow", "-crf", "18", "-pix_fmt", "yuv420p", output_file
+ ]
+ slice_pipes.append(subprocess.Popen(ffmpeg_encode, stdin=subprocess.PIPE, bufsize=frame_size * 1))
+
+ # 璇诲彇甯у苟鍒嗛厤鍒板搴旂殑鍒囩墖绠¢亾
+ current_frame = 0
+ while True:
+ frame_data = process_extract.stdout.read(frame_size)
+ if len(frame_data) < frame_size:
+ break # 璇诲彇缁撴潫
+
+ # 鎵惧埌褰撳墠甯ф墍灞炵殑鍒囩墖娈�
+ for i, (start_frame, end_frame) in enumerate(zip(frame_segments[:-1], frame_segments[1:])):
+ if start_frame <= current_frame < end_frame:
+ print(i)
+ slice_pipes[i].stdin.write(frame_data)
+ break
+
+ current_frame += 1
+
+ # 鍏抽棴鎵�鏈夌閬�
+ process_extract.stdout.close()
+ process_extract.wait()
+ for pipe in slice_pipes:
+ pipe.stdin.close()
+ pipe.wait()
+
+ print(f"瑙嗛鍒嗘瀹屾垚锛屽垏鐗囧瓨鍌ㄥ湪锛歿output_dir}")
+
+
+
+# 绀轰緥浣跨敤
+video_path = "E:/鎶栭煶-AI椋庢櫙/Test/demo.mp4"
+frame_segments = [0, 60, 69, 305]
+fps = 30
+width, height = 1080, 1440
+output_dir = "output"
+
+split_video_by_pipe(video_path, frame_segments, width,height, output_dir)
\ No newline at end of file
diff --git a/test/pipe_test.py b/test/pipe_test.py
new file mode 100644
index 0000000..5e9d7ff
--- /dev/null
+++ b/test/pipe_test.py
@@ -0,0 +1,60 @@
+import subprocess
+import os
+
+def test_pipeline_to_multiple_slices(video_path):
+ frame_segments = [(0, 60), (60, 79), (79, 98), (98, 116), (116, 135),
+ (135, 153), (153, 172), (172, 190), (190, 209),
+ (209, 228), (228, 247), (247, 266), (266, 285), (285, 305)] # 甯у尯闂�
+
+ # 鍚姩 FFmpeg 浠ヨ鍙栬棰戝抚鏁版嵁骞堕�氳繃绠¢亾杈撳嚭
+ ffmpeg_extract = [
+ "ffmpeg", "-i", video_path, "-vf", "fps=30", "-f", "image2pipe", "-vcodec", "png", "-"
+ ]
+ process_extract = subprocess.Popen(ffmpeg_extract, stdout=subprocess.PIPE, bufsize=10**8) # 浣跨敤杈冨ぇ缂撳啿鍖�
+
+ # 鍒涘缓澶氫釜瀛愯繘绋嬶紝澶勭悊瑙嗛鍒囩墖
+ slice_processes = []
+ output_pipes = []
+
+ for i, (start_frame, end_frame) in enumerate(frame_segments):
+ output_file = f"slice_{i+1}.mp4"
+ ffmpeg_encode = [
+ "ffmpeg", "-framerate", "30", "-f", "image2pipe", "-vcodec", "png", "-i", "-",
+ "-c:v", "libx264", "-preset", "slow", "-crf", "0", "-pix_fmt", "yuv420p", output_file
+ ]
+ process = subprocess.Popen(ffmpeg_encode, stdin=subprocess.PIPE)
+ slice_processes.append(process)
+ output_pipes.append((process.stdin, start_frame, end_frame))
+
+ current_frame = 0
+
+ try:
+ while True:
+ frame_data = process_extract.stdout.read(1024*1024) # 姣忔璇诲彇 1MB锛岀洿鍒版棤鏁版嵁
+ if not frame_data:
+ break # 褰撹鍙栧埌瑙嗛缁撴潫鏃惰烦鍑哄惊鐜�
+
+ # 鍒嗗彂甯ф暟鎹埌鍚堥�傜殑瀛愯繘绋�
+ for pipe, start_frame, end_frame in output_pipes:
+ if start_frame <= current_frame < end_frame:
+ pipe.write(frame_data) # 鍐欏叆甯ф暟鎹�
+ break
+
+ current_frame += 1
+
+ finally:
+ # 鍏抽棴鎵�鏈夊瓙杩涚▼鐨勮緭鍏ユ祦
+ for pipe, _, _ in output_pipes:
+ pipe.close()
+
+ # 绛夊緟鎵�鏈夊瓙杩涚▼瀹屾垚
+ for process in slice_processes:
+ process.wait()
+
+ # 鍏抽棴鎻愬彇杩涚▼鐨勮緭鍑烘祦
+ process_extract.stdout.close()
+ process_extract.wait()
+
+if __name__ == "__main__":
+ video_path = "E:/鎶栭煶-AI椋庢櫙/Test/demo.mp4"
+ test_pipeline_to_multiple_slices(video_path)
diff --git a/test/pygame_test.py b/test/pygame_test.py
new file mode 100644
index 0000000..b526ac8
--- /dev/null
+++ b/test/pygame_test.py
@@ -0,0 +1,107 @@
+import pygame
+import subprocess
+import threading
+import time
+import tkinter as tk
+from tkinter import ttk
+
+class VideoPlayer:
+ def __init__(self, root, video_path):
+ self.root = root
+ self.video_path = video_path
+ self.is_paused = False
+ self.is_running = True
+ self.current_position = 0
+
+ # 鍒濆鍖� pygame
+ pygame.init()
+ self.screen = pygame.display.set_mode((640, 480))
+ pygame.display.set_caption("瑙嗛鎾斁鍣�")
+
+ # 鍒涘缓 Tkinter 鎺т欢
+ self.canvas = tk.Canvas(root, width=640, height=480)
+ self.canvas.pack()
+
+ self.play_button = tk.Button(root, text="鎾斁/鏆傚仠", command=self.toggle_pause)
+ self.play_button.pack(side=tk.LEFT)
+
+ self.restart_button = tk.Button(root, text="閲嶆柊鎾斁", command=self.restart_video)
+ self.restart_button.pack(side=tk.LEFT)
+
+ self.progress = ttk.Scale(root, from_=0, to=100, orient=tk.HORIZONTAL, command=self.update_position)
+ self.progress.pack(fill=tk.X, expand=True)
+
+ # 鍚姩鎾斁瑙嗛绾跨▼
+ self.video_thread = threading.Thread(target=self.play_video)
+ self.video_thread.start()
+
+ def toggle_pause(self):
+ """鍒囨崲鎾斁/鏆傚仠鐘舵��"""
+ if self.is_paused:
+ self.is_paused = False
+ else:
+ self.is_paused = True
+
+ def restart_video(self):
+ """閲嶆柊寮�濮嬫挱鏀�"""
+ self.is_paused = False
+ self.progress.set(0)
+ self.play_video()
+
+ def update_position(self, value):
+ """鏇存柊杩涘害鏉′綅缃�"""
+ self.current_position = float(value)
+
+ def play_video(self):
+ """鎾斁瑙嗛骞舵洿鏂拌繘搴︽潯"""
+ # 浣跨敤 subprocess 鎾斁瑙嗛骞舵彁鍙栧抚
+ ffmpeg_cmd = [
+ "ffmpeg", "-i", self.video_path, "-f", "image2pipe", "-pix_fmt", "rgb24",
+ "-vcodec", "rawvideo", "-"]
+
+ # 鍒涘缓 subprocess 鏉ユ墽琛� ffmpeg 鍛戒护
+ process = subprocess.Popen(ffmpeg_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+
+ frame_count = 0
+ while self.is_running:
+ if self.is_paused:
+ time.sleep(0.1)
+ continue
+
+ # 浠� ffmpeg 鎻愬彇涓�甯�
+ raw_frame = process.stdout.read(640 * 480 * 3) # 璇诲彇涓�甯э紙RGB24锛�
+ if len(raw_frame) < 640 * 480 * 3:
+ break # 濡傛灉璇诲彇鐨勫抚涓嶅畬鏁达紝鍒欏仠姝�
+
+ frame = pygame.image.fromstring(raw_frame, (640, 480), 'RGB')
+ self.screen.blit(frame, (0, 0))
+ pygame.display.flip() # 鏇存柊灞忓箷
+
+ frame_count += 1
+ self.update_progress(frame_count)
+
+ time.sleep(0.04) # 鎺у埗甯х巼 (鍋囪瑙嗛鐨勫抚鐜囨槸 25 FPS)
+
+ process.wait() # 绛夊緟瑙嗛鎾斁缁撴潫
+ self.restart_video() # 鎾斁缁撴潫鍚庤嚜鍔ㄩ噸鎾�
+
+ def update_progress(self, frame_count):
+ """鏇存柊杩涘害鏉�"""
+ video_duration = 120 # 鎵嬪姩璁剧疆瑙嗛鏃堕暱锛屾垨鑰呴�氳繃鍏朵粬鏂瑰紡鑾峰彇鏃堕暱
+ progress_percentage = (frame_count / (25 * video_duration)) * 100
+ self.progress.set(progress_percentage)
+
+ def close(self):
+ """鍏抽棴瑙嗛鎾斁鍣�"""
+ self.is_running = False
+ self.video_thread.join()
+
+# 鍒涘缓 Tkinter 绐楀彛
+root = tk.Tk()
+root.title("瑙嗛鎾斁鍣�")
+
+media_path = "E:/鎶栭煶-AI椋庢櫙/data/鍏虫敞/1515593476095344/瑙嗛/7375164244729302272.mp4" # 鏇挎崲涓哄疄闄呰棰戞枃浠惰矾寰�
+player = VideoPlayer(root, media_path)
+
+root.protocol("WM_DELETE_WINDOW", player.close)
+root.mainloop()
diff --git a/test/refresh.py b/test/refresh.py
new file mode 100644
index 0000000..81b1f52
--- /dev/null
+++ b/test/refresh.py
@@ -0,0 +1,24 @@
+import tkinter as tk
+from tkinter import filedialog
+
+def open_folder():
+ folder_path = filedialog.askdirectory()
+ if folder_path:
+ # 鍋囪璁$畻鏂囦欢鏁伴噺
+ file_count = 5 # 绀轰緥鍊�
+ print("姝e湪鏇存柊鏂囦欢鏁伴噺...")
+ file_count_label.config(text="鏂囦欢鏁伴噺锛�" + str(file_count))
+ root.update() # 鍒锋柊鐣岄潰
+
+root = tk.Tk()
+root.geometry("400x200")
+
+# 娣诲姞涓�涓� Label
+file_count_label = tk.Label(root, text="鏂囦欢鏁伴噺锛�0")
+file_count_label.pack(pady=10)
+
+# 娣诲姞鎸夐挳
+open_button = tk.Button(root, text="鎵撳紑鏂囦欢澶�", command=open_folder)
+open_button.pack(pady=20)
+
+root.mainloop()
diff --git a/test/scene_detect_demo.py b/test/scene_detect_demo.py
new file mode 100644
index 0000000..a4a9f6e
--- /dev/null
+++ b/test/scene_detect_demo.py
@@ -0,0 +1,69 @@
+import cv2
+from scenedetect import detect, ContentDetector
+from moviepy.editor import VideoFileClip
+
+import sys
+# 妫�娴嬭棰戜腑鐨勫満鏅�
+scene_list = detect(sys.argv[1], ContentDetector())
+
+frame_list = []
+
+for i, scene in enumerate(scene_list):
+ if i==0:
+ print(scene[0].get_frames(),scene[1].get_frames()+2)
+ frame_list.append([scene[0].get_frames(),scene[1].get_frames()+2])
+ elif i==len(scene_list)-1:
+ print(scene[0].get_frames()+2,scene[1].get_frames())
+ frame_list.append([scene[0].get_frames()+2,scene[1].get_frames()])
+ else:
+ print(scene[0].get_frames()+2,scene[1].get_frames()+2)
+ frame_list.append([scene[0].get_frames()+2,scene[1].get_frames()+2])
+
+
+# 鎵撳紑鍘熷瑙嗛
+video_clip = VideoFileClip(sys.argv[1])
+
+# 閬嶅巻鍦烘櫙骞朵繚瀛樹负鏂扮殑 MP4 鏂囦欢
+for i, (start_frame, end_frame) in enumerate(scene_list):
+ # 灏嗗抚鏁拌浆鎹负绉�
+ start_time = start_frame.get_seconds() # 浣跨敤 get_seconds() 杞崲涓虹
+ end_time = end_frame.get_seconds() # 浣跨敤 get_seconds() 杞崲涓虹
+
+ # 鍒囧壊瑙嗛
+ scene_clip = video_clip.subclip(start_time, end_time)
+
+ # 璁剧疆杈撳嚭鏂囦欢鍚�
+ output_filename = f"oringal_{i+1}.mp4"
+
+ # 淇濆瓨鍦烘櫙涓� MP4 鏂囦欢
+ scene_clip.write_videofile(output_filename, codec="libx264", fps=video_clip.fps)
+
+ print(f"Scene {i+1} has been saved as {output_filename}")
+
+# 鍏抽棴瑙嗛鏂囦欢
+video_clip.close()
+
+# 鎵撳紑鍘熷瑙嗛
+video_clip = VideoFileClip(sys.argv[1])
+fps =video_clip.fps
+# 閬嶅巻鍦烘櫙骞朵繚瀛樹负鏂扮殑 MP4 鏂囦欢
+for index,item in enumerate(frame_list):
+ # 灏嗗抚鏁拌浆鎹负绉�
+ start_time = item[0]/fps
+ end_time = item[1]/fps
+
+ # 鍒囧壊瑙嗛
+ scene_clip = video_clip.subclip(start_time, end_time)
+
+ # 璁剧疆杈撳嚭鏂囦欢鍚�
+ output_filename = f"modified_{index+1}.mp4"
+
+ # 淇濆瓨鍦烘櫙涓� MP4 鏂囦欢
+ scene_clip.write_videofile(output_filename, codec="libx264", fps=video_clip.fps)
+
+ print(f"Scene {i+1} has been saved as {output_filename}")
+
+# 鍏抽棴瑙嗛鏂囦欢
+video_clip.close()
+
+
diff --git a/test/sence_detect_demo.py b/test/sence_detect_demo.py
new file mode 100644
index 0000000..c0d211b
--- /dev/null
+++ b/test/sence_detect_demo.py
@@ -0,0 +1,70 @@
+import cv2
+from scenedetect import detect, ContentDetector
+
+# 妫�娴嬭棰戜腑鐨勫満鏅�
+scene_list = detect('demo3.mp4', ContentDetector())
+
+# 瀛樺偍淇敼鍚庣殑鍦烘櫙淇℃伅
+modified_scene_list = []
+
+# 閬嶅巻鍦烘櫙
+for i, scene in enumerate(scene_list):
+ if i == 0:
+ # 绗竴涓満鏅洿鎺ユ坊鍔�
+ modified_scene_list.append(scene)
+ elif i == len(scene_list) - 1:
+ # 鏈�鍚庝竴涓満鏅笉澶勭悊
+ modified_scene_list.append(scene)
+ else:
+ # 浠庣浜屼釜鍦烘櫙寮�濮嬶紝澶勭悊鍓嶄袱甯�
+ current_scene_start_frame = scene[0].get_frames()
+ current_scene_end_frame = scene[1].get_frames()
+
+ # 鑾峰彇鍓嶄竴涓満鏅�
+ previous_scene = modified_scene_list[-1]
+
+ # 鑾峰彇鍓嶄竴涓満鏅殑缁撴潫甯�
+ previous_scene_end_frame = previous_scene[1].get_frames()
+
+ # 鏇存柊鍓嶄竴涓満鏅殑缁撴潫甯э紝灏嗗綋鍓嶅満鏅殑鍓嶄袱甯ф嫾鎺ュ埌鍓嶄竴涓満鏅悗闈�
+ modified_previous_scene_end_frame = previous_scene_end_frame + 2
+
+ # 鏇存柊鍓嶄竴涓満鏅殑缁撴潫鏃堕棿
+ modified_scene_list[-1] = (previous_scene[0], scene[0])
+
+ # 娣诲姞褰撳墠鍦烘櫙锛堝幓鎺夊墠涓ゅ抚锛�
+ modified_scene_list.append((scene[0], scene[1]))
+
+# 鎵撳紑鍘熷瑙嗛
+cap = cv2.VideoCapture('demo3.mp4')
+fps = cap.get(cv2.CAP_PROP_FPS) # 鑾峰彇甯х巼
+frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) # 鑾峰彇甯у搴�
+frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) # 鑾峰彇甯ч珮搴�
+
+# 瀵规瘡涓満鏅繘琛屽垏鍓插苟淇濆瓨涓� MP4
+for i, scene in enumerate(modified_scene_list):
+ start_frame = scene[0].get_frames()
+ end_frame = scene[1].get_frames()
+
+ # 璁剧疆瑙嗛璇诲彇鐨勮捣濮嬩綅缃�
+ cap.set(cv2.CAP_PROP_POS_FRAMES, start_frame)
+
+ # 鍒涘缓涓�涓� VideoWriter 瀵硅薄锛岀敤浜庝繚瀛樺綋鍓嶅満鏅负鏂扮殑 MP4 鏂囦欢
+ output_filename = f'scene_{i+1}.mp4'
+ fourcc = cv2.VideoWriter_fourcc(*'H264') # 浣跨敤 H.264 缂栫爜鍣�
+ out = cv2.VideoWriter(output_filename, fourcc, fps, (frame_width, frame_height)) # 瑙嗛鍒嗚鲸鐜�
+
+ # 璇诲彇姣忎竴甯у苟鍐欏叆鍒拌緭鍑烘枃浠朵腑
+ for frame_num in range(start_frame, end_frame):
+ ret, frame = cap.read()
+ if not ret:
+ break
+ out.write(frame)
+
+ # 閲婃斁 VideoWriter 鍜� VideoCapture 瀵硅薄
+ out.release()
+
+ print(f'Scene {i+1} has been saved as {output_filename}')
+
+# 閲婃斁 VideoCapture 瀵硅薄
+cap.release()
diff --git a/test/t_ffmpeg.py b/test/t_ffmpeg.py
new file mode 100644
index 0000000..0774c9b
--- /dev/null
+++ b/test/t_ffmpeg.py
@@ -0,0 +1,3 @@
+from scenedetect import detect, ContentDetector, split_video_ffmpeg
+scene_list = detect('demo.mp4', ContentDetector())
+split_video_ffmpeg('demo.mp4', scene_list)
\ No newline at end of file
diff --git a/test/t_ssim.py b/test/t_ssim.py
new file mode 100644
index 0000000..4b539e4
--- /dev/null
+++ b/test/t_ssim.py
@@ -0,0 +1,66 @@
+import cv2
+from skimage.metrics import structural_similarity as ssim
+import numpy as np
+
+class VideoSSIM:
+ def __init__(self, video_path):
+ # 鍒濆鍖栬棰戣矾寰勫拰鎵撳紑瑙嗛
+ self.video_path = video_path
+ self.cap = cv2.VideoCapture(video_path)
+ if not self.cap.isOpened():
+ raise ValueError(f"Error opening video file: {video_path}")
+
+ # 鑾峰彇瑙嗛甯х巼锛坒ps锛�
+ self.fps = self.cap.get(cv2.CAP_PROP_FPS)
+
+ # 鑾峰彇瑙嗛鐨勫昂瀵�
+ self.frame_width = int(self.cap.get(cv2.CAP_PROP_FRAME_WIDTH))
+ self.frame_height = int(self.cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
+
+ def calculate_ssim(self):
+ # 璇诲彇瑙嗛鐨勭涓�甯�
+ ret, prev_frame = self.cap.read()
+ if not ret:
+ raise ValueError("Error reading the first frame")
+
+ prev_frame_gray = cv2.cvtColor(prev_frame, cv2.COLOR_BGR2GRAY) # 杞崲涓虹伆搴﹀浘
+
+ # 瀛樺偍鐩镐技鎬ф暟鍊�
+ ssim_values = []
+
+ # 浠庣浜屽抚寮�濮嬮�愬抚璁$畻涓庡墠涓�甯х殑缁撴瀯鐩镐技鎬�
+ frame_index = 2 # 浠庣浜屽抚寮�濮�
+ while True:
+ ret, curr_frame = self.cap.read()
+ if not ret:
+ break
+
+ # 杞崲褰撳墠甯т负鐏板害鍥�
+ curr_frame_gray = cv2.cvtColor(curr_frame, cv2.COLOR_BGR2GRAY)
+
+ # 璁$畻SSIM
+ ssim_value, _ = ssim(prev_frame_gray, curr_frame_gray, full=True)
+ ssim_values.append((frame_index, ssim_value)) # 璁板綍甯х储寮曞拰SSIM鍊�
+
+ # 鏇存柊鍓嶄竴甯�
+ prev_frame_gray = curr_frame_gray
+ frame_index += 1
+
+ # 閲婃斁瑙嗛鎹曟崏瀵硅薄
+ self.cap.release()
+
+ return ssim_values
+
+ def save_ssim_to_file(self, output_file="ssim_values.txt"):
+ ssim_values = self.calculate_ssim()
+
+ # 淇濆瓨SSIM鍊煎埌鏂囦欢
+ with open(output_file, "w") as f:
+ for frame_idx, ssim_value in ssim_values:
+ f.write(f"Frame {frame_idx}: SSIM = {ssim_value}\n")
+
+ print(f"SSIM values saved to {output_file}")
+
+# 浣跨敤绀轰緥
+video_ssim = VideoSSIM("demo.mp4") # 鏇挎崲鎴愪綘鐨勮棰戞枃浠惰矾寰�
+video_ssim.save_ssim_to_file("demo_ssim_output.txt")
diff --git a/test/test_cv.py b/test/test_cv.py
new file mode 100644
index 0000000..409602f
--- /dev/null
+++ b/test/test_cv.py
@@ -0,0 +1,94 @@
+import cv2
+import numpy as np
+import os
+import time
+
+def read_video_to_memory(video_path):
+ """
+ 璇诲彇 MP4 瑙嗛骞跺皢姣忎竴甯у瓨鍌ㄥ埌鍐呭瓨涓�
+ """
+ start_time = time.time()
+ cap = cv2.VideoCapture(video_path)
+ frames = []
+
+ # 鑾峰彇瑙嗛鐨勬�诲抚鏁板拰甯х巼
+ total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
+ fps = cap.get(cv2.CAP_PROP_FPS)
+
+ print(total_frames)
+
+ print(fps)
+
+ while True:
+ ret, frame = cap.read()
+ if not ret:
+ break
+ frames.append(frame)
+
+ cap.release()
+ print(time.time() -start_time )
+ return frames, fps, total_frames
+
+def generate_thumbnail(frame, max_size=144):
+ """
+ 鐢熸垚涓嶈秴杩囨寚瀹氬ぇ灏忕殑缂╃暐鍥�
+ """
+ height, width = frame.shape[:2]
+
+ # 纭畾缂╂斁姣斾緥
+ scale = min(max_size / height, max_size / width)
+ new_width = int(width * scale)
+ new_height = int(height * scale)
+
+ # 缂╂斁骞惰繑鍥炵缉鐣ュ浘
+ thumbnail = cv2.resize(frame, (new_width, new_height))
+ return thumbnail
+
+def save_video_slice(frames, slice_range, output_file, fps):
+ """
+ 鏍规嵁鎸囧畾鐨勫抚鑼冨洿灏嗚棰戜繚瀛樹负鏂扮殑鐗囨
+ """
+ fourcc = cv2.VideoWriter_fourcc(*'mp4v') # 鐢ㄤ簬鐢熸垚 MP4 鏍煎紡
+ height, width = frames[0].shape[:2]
+ out = cv2.VideoWriter(output_file, fourcc, fps, (width, height))
+
+ start_frame, end_frame = slice_range
+
+ # 閬嶅巻鎸囧畾鑼冨洿鐨勫抚骞跺啓鍏ュ埌鏂拌棰戜腑
+ for i in range(start_frame, end_frame):
+ out.write(frames[i])
+
+ out.release()
+
+def create_video_slice_from_memory(video_path, slice_segments, output_dir):
+ """
+ 浠庡唴瀛樹腑鐨勮棰戝抚鍒涘缓澶氫釜瑙嗛鐗囨
+ """
+ frames, fps, total_frames = read_video_to_memory(video_path)
+
+ start_time = time.time()
+ # 鐢熸垚缂╃暐鍥惧苟鏄剧ず
+ thumbnails = []
+ for frame in frames:
+ thumbnails.append(generate_thumbnail(frame))
+
+ print(time.time()-start_time)
+
+
+ # 鏍规嵁鍒囩墖鍒嗗壊瑙嗛骞朵繚瀛�
+ for i, (start_frame, end_frame) in enumerate(slice_segments):
+ output_file = os.path.join(output_dir, f"slice_{i+1}.mp4")
+ start_time = time.time()-start_time
+ save_video_slice(frames, (start_frame, end_frame), output_file, fps)
+ print(time.time()-start_time)
+
+
+# 绀轰緥锛氳鍙栬棰戝苟鍒涘缓澶氫釜鍒囩墖
+video_path = "E:/鎶栭煶-AI椋庢櫙/Test/demo.mp4"
+slice_segments = [(0, 60),(60, 79), (79,98),(98,116), (116,135),(135, 153), (153,172), (172,190), (190,209), (209,228), (228,247), (247,266), (266,285),(285,303)] # 瀹氫箟甯у尯闂�
+output_dir = "output_slices"
+
+if not os.path.exists(output_dir):
+ os.makedirs(output_dir)
+
+create_video_slice_from_memory(video_path, slice_segments, output_dir)
diff --git a/test/tk.py b/test/tk.py
new file mode 100644
index 0000000..a03c1bf
--- /dev/null
+++ b/test/tk.py
@@ -0,0 +1,77 @@
+import subprocess
+import os
+
+import re
+
+
+def cut_video_by_frames(video_path, frame_segments, total_frames, output_dir):
+ """
+ 灏嗚棰戞寜鐓ф寚瀹氱殑甯у垏鐗囪繘琛屽垏鍓层��
+
+ 鍙傛暟锛�
+ - video_path: 杈撳叆瑙嗛鐨勮矾寰�
+ - frame_segments: 鍒囩墖鐨勫抚搴忓彿鏁扮粍锛屼緥濡傦細[0, M1, M2, ..., Mlast]
+ - output_dir: 杈撳嚭瑙嗛鏂囦欢鐨勭洰褰�
+ """
+ fps = 30 # default fps
+
+ # 鑾峰彇瑙嗛鐨勫抚鐜� (fps)
+ command = [
+ "ffmpeg", "-i", video_path, "-vf", "fps=1", "-f", "null", "-"
+ ]
+ result = subprocess.run(command, stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE, text=True)
+ output = result.stderr
+ # 瑙f瀽 fps锛屾煡鎵句俊鎭�
+ fps_line = next(line for line in output.splitlines() if 'fps' in line)
+ # 浣跨敤姝e垯琛ㄨ揪寮忔彁鍙栧抚鐜囧�硷紙鍋囪fps鍊兼�绘槸鍑虹幇鍦�"fps"鍓嶉潰锛�
+ match = re.search(r'(\d+(\.\d+)?)\s*fps', fps_line)
+ if match:
+ fps = float(match.group(1)) # 鎻愬彇骞惰浆鎹负 float
+ print(f"FPS: {fps}")
+
+ print(f"瑙嗛鐨勬�诲抚鏁�: {total_frames}, 甯х巼: {fps}")
+
+ # 閬嶅巻鍒囩墖鍖洪棿
+ for i in range(len(frame_segments) - 1):
+ start_frame = frame_segments[i]
+ end_frame = frame_segments[i + 1]
+
+
+ start_time = float(start_frame) / fps
+ end_time = float(end_frame) / fps
+
+ output_file = os.path.join(output_dir, f"segment_{i + 1}.mp4")
+
+
+ # 浣跨敤 FFmpeg 鍛戒护鏉ュ垏鍓茶棰�
+ command = [
+ "ffmpeg", "-i", video_path, "-ss", f"{start_time:.10f}", "-to", f"{end_time:.10f}",
+ "-c:v", "libx264", "-c:a", "copy","-crf", "18","-preset", "veryslow", output_file
+ ]
+ print(" ".join(command))
+
+ subprocess.run(command)
+
+ # 鏈�鍚庝竴娈靛鐞嗭紙浠庢渶鍚庝竴涓垏鐗囧埌瑙嗛缁撴潫锛�
+ last_start_frame = frame_segments[-1]
+ last_start_time = last_start_frame / fps
+ output_file = os.path.join(
+ output_dir, f"segment_{len(frame_segments)}.mp4")
+
+ #print(f"姝e湪鍒囧壊鏈�鍚庝竴娈碉細浠� {last_start_time:.10f}s 鍒拌棰戠粨鏉燂紝淇濆瓨涓� {output_file}")
+ command = [
+ "ffmpeg", "-i", video_path, "-ss", f"{last_start_time:.10f}",
+ "-c:v", "libx264", "-c:a", "copy","-crf", "18","-preset", "veryslow", output_file
+ ]
+ print(" ".join(command))
+ subprocess.run(command)
+
+
+target_file = "E:/鎶栭煶-AI椋庢櫙/鏂板缓鏂囦欢澶筡_demoold.mp4"
+selected_labels = [0, 60, 79, 98, 116, 135,
+ 153, 172, 190, 209, 228, 246, 264, 283]
+frame_count = 305
+output_dir = "E:/鎶栭煶-AI椋庢櫙/鏂板缓鏂囦欢澶筡ProcessResults"
+
+cut_video_by_frames(target_file, selected_labels, frame_count, output_dir)
diff --git a/test/vlc_test.py b/test/vlc_test.py
new file mode 100644
index 0000000..ed5d492
--- /dev/null
+++ b/test/vlc_test.py
@@ -0,0 +1,106 @@
+import tkinter as tk
+from tkinter import ttk
+import vlc
+import os
+
+
+class VideoPlayer:
+ def __init__(self, root):
+ self.root = root
+ self.player = vlc.Instance()
+ self.is_playing = False
+ self.is_paused = False
+ self.listPlayer = None
+ self.create_ui()
+
+ def create_ui(self):
+ # Canvas to display video
+ self.canvas = tk.Canvas(self.root, width=640, height=360)
+ self.canvas.pack()
+
+ # Create play, pause, and stop buttons
+ self.play_button = tk.Button(self.root, text="Play", command=self.toggle_play_pause)
+ self.play_button.pack(side=tk.LEFT)
+
+ self.stop_button = tk.Button(self.root, text="Stop", command=self.stop)
+ self.stop_button.pack(side=tk.LEFT)
+
+ # Progress bar for video
+ self.progress_bar = ttk.Scale(self.root, from_=0, to=100, orient="horizontal", length=500, command=self.on_progress_drag)
+ self.progress_bar.pack()
+
+ # Start a thread to update progress bar
+ self.update_progress_task()
+
+ def add_video(self, video_path):
+ # Create media list and add video
+ self.mediaList = self.player.media_list_new()
+ self.media = self.player.media_new(video_path)
+ self.mediaList.add_media(self.media)
+
+ # Create MediaListPlayer and associate it with the media list
+ self.listPlayer = self.player.media_list_player_new()
+ self.listPlayer.set_media_list(self.mediaList)
+ self.listPlayer.set_playback_mode(vlc.PlaybackMode(1))
+
+ def play(self):
+ if self.listPlayer:
+ self.listPlayer.play()
+ self.is_playing = True
+ self.is_paused = False
+ self.play_button.config(text="Pause")
+
+ def stop(self):
+ if self.listPlayer:
+ self.listPlayer.stop()
+ self.is_playing = False
+ self.is_paused = False
+ self.play_button.config(text="Play")
+
+ def toggle_play_pause(self):
+ if self.is_playing:
+ self.listPlayer.pause()
+ self.is_playing = False
+ self.is_paused = True
+ self.play_button.config(text="Resume")
+ elif self.is_paused:
+ self.listPlayer.play()
+ self.is_playing = True
+ self.is_paused = False
+ self.play_button.config(text="Pause")
+ else:
+ self.play()
+
+ def update_progress_task(self):
+ # Continuously update the progress bar
+ if self.listPlayer:
+ current_time = self.listPlayer.get_media_player().get_time() # Get current playback time
+ duration = self.listPlayer.get_media_player().get_length() # Get video duration
+ if duration > 0:
+ progress = (current_time / duration) * 100 # Calculate progress percentage
+ self.progress_bar.set(progress)
+
+ # Call the function every 100 ms
+ self.root.after(100, self.update_progress_task)
+
+ def on_progress_drag(self, value):
+ # Seek the video to the dragged position
+ if self.listPlayer:
+ duration = self.listPlayer.get_media_player().get_length()
+ new_time = (float(value) / 100) * duration
+ self.listPlayer.get_media_player().set_time(int(new_time))
+
+
+def main():
+ root = tk.Tk()
+ root.title("VLC Video Player")
+
+ video_player = VideoPlayer(root)
+ video_path = "E:/鎶栭煶-AI椋庢櫙/data/鍏虫敞/1515593476095344/瑙嗛/7375164244729302272.mp4" # 鏇挎崲涓哄疄闄呰棰戞枃浠惰矾寰�
+ video_player.add_video(video_path) # Replace with the path to your video
+ # Start the Tkinter main loop
+ root.mainloop()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/tkv.py b/tkv.py
deleted file mode 100644
index 71c10b1..0000000
--- a/tkv.py
+++ /dev/null
@@ -1,467 +0,0 @@
-import tkinter as tk
-from tkinter import filedialog, messagebox, ttk,Canvas
-import os
-import numpy as np
-from PIL import Image, ImageTk
-import vlc
-import subprocess
-import functools
-import re
-
-
-# Global variables
-video_files = [] # List of video files
-current_video_idx = 0 # Index of the current video
-current_video_path = ""
-video_player = None
-thumbnail_images = []
-split_info = []
-
-# Create the main window
-root = tk.Tk()
-root.title("Video Processing Tool")
-root.state('zoomed') # Fullscreen
-
-screen_width = root.winfo_screenwidth()
-screen_height = root.winfo_screenheight()
-
-
-# Video playing frame
-video_frame = tk.Frame(root, width=1080, height=1920)
-video_frame.pack(side=tk.LEFT, padx=0)
-
-# Frame for thumbnail images
-thumbnail_frame = tk.Frame(root, width=1080, height=1920)
-thumbnail_frame.pack_forget()
-
-# Frame for right-side info and buttons
-control_frame = tk.Frame(root, width=100, height=200, bg='yellow')
-control_frame.pack(side=tk.RIGHT, anchor="ne", padx=5, pady=5)
-
-# 绾跨▼鍑芥暟鏉ユ樉绀鸿棰�
-
-def on_playback_ended(event):
- # player.play()
- video_frame.pack_forget() # 濡傛灉浣跨敤 pack()
- global current_video_path
- display_thumbnails(current_video_path)
-
-
-def toggle_play_pause():
- if player.is_playing():
- player.pause() # 鏆傚仠鎾斁
- play_pause_button.config(text="鎾斁瑙嗛") # 鏇存柊鎸夐挳鏂囨湰涓烘挱鏀�
- else:
- player.play() # 鎾斁
- play_pause_button.config(text="鏆傚仠瑙嗛") # 鏇存柊鎸夐挳鏂囨湰涓烘殏鍋�
-
-# 鏇存柊杩涘害鏉″苟澧炲姞璋冭瘯淇℃伅
-
-
-def update_progress():
- # 纭繚鎾斁鍣ㄦ鍦ㄦ挱鏀�
- if player.is_playing():
- current_time = player.get_time() / 1000 # 姣杞负绉�
- total_time = player.get_length() / 1000 # 姣杞负绉�
- if total_time > 0:
- progress_percentage = (current_time / total_time) * 100
- progress_var.set(progress_percentage)
- progress_bar.after(50, update_progress)
- else:
- progress_bar.after(50, update_progress)
-
-
-def get_thumbnail_frames(video_file):
- # 鑾峰彇鍚屽悕鏂囦欢澶硅矾寰�
- base_dir = os.path.dirname(video_file)
- video_name = os.path.splitext(os.path.basename(video_file))[0]
- thumbnail_dir = os.path.join(base_dir, video_name)
-
- # 濡傛灉鏂囦欢澶逛笉瀛樺湪锛岃皟鐢� bat 鏂囦欢澶勭悊
- if not os.path.exists(thumbnail_dir):
- print(f"鏂囦欢澶� {thumbnail_dir} 涓嶅瓨鍦紝璋冪敤 bat 鏂囦欢杩涜澶勭悊...")
- subprocess.run(['mp4_generate_thumbnails.bat', video_file], check=True)
-
- # 閲嶆柊鑾峰彇鏂囦欢澶瑰唴鐨勬墍鏈� jpg 鏂囦欢
- jpg_files = [os.path.join(thumbnail_dir, f) for f in os.listdir(
- thumbnail_dir) if f.lower().endswith('.jpg')]
- jpg_files.sort() # 鎸夌収鏂囦欢鍚嶉『搴忔帓搴�
-
- return jpg_files
-
-selected_labels = [] # 璁板綍褰撳墠閫変腑鐨勬爣绛�
-thumbnails = []
-
-def display_thumbnails(video_file):
- global thumbnails, selected_labels
- thumbnails = get_thumbnail_frames(video_file)
- row, col = 0, 0
- max_col = (screen_width - 100) // 90 - 1 # 鍔ㄦ�佸湴
-
- # 鍒涘缓Canvas鍜屽瀭鐩存粴鍔ㄦ潯
- thumbnail_frame.pack(side=tk.LEFT, padx=0)
-
- canvas = tk.Canvas(thumbnail_frame, width=screen_width - 100, height=screen_height)
- canvas.grid(row=0, column=0, sticky='nsew')
-
- scrollbar = ttk.Scrollbar(thumbnail_frame, orient="vertical", command=canvas.yview)
- scrollbar.grid(row=0, column=1, sticky='ns')
-
- canvas.configure(yscrollcommand=scrollbar.set)
-
- # 鍒涘缓涓�涓猣rame浣滀负Canvas鐨勫瓙椤规潵娣诲姞缂╃暐鍥�
- thumbnail_container = tk.Frame(canvas)
- canvas.create_window((0, 0), window=thumbnail_container, anchor="nw")
-
- # 鍚敤榧犳爣婊氳疆浜嬩欢鏉ユ粴鍔–anvas
- def on_mouse_wheel(event):
- """澶勭悊榧犳爣婊氳疆浜嬩欢"""
- canvas.yview_scroll(int(-1 * (event.delta / 120)), "units")
-
- # 缁戝畾榧犳爣婊氳疆浜嬩欢
- canvas.bind_all("<MouseWheel>", on_mouse_wheel)
-
- # 娣诲姞缂╃暐鍥�
- for idx, thumb in enumerate(thumbnails):
- # 浣跨敤PIL鍔犺浇鍥剧墖
- pil_image = Image.open(thumb)
-
- # 杞崲涓篢kinter鍙樉绀虹殑鏍煎紡
- photo = ImageTk.PhotoImage(pil_image)
-
- # 鍒涘缓涓�涓爣绛炬樉绀哄浘鍍�
- thumb_label = tk.Label(thumbnail_container, image=photo)
- thumb_label.image = photo # 蹇呴』淇濇寔瀵瑰浘鍍忕殑寮曠敤
- thumb_label.grid(row=row, column=col, padx=1, pady=1)
-
- # 灏唗oggle_checkmark鐨勮皟鐢ㄧ敤 functools.partial鍖呰锛屼紶閫抜dx
- thumb_label.bind("<Button-1>", functools.partial(toggle_checkmark, label=thumb_label, idx=idx))
-
- checkmark_label = None
- if idx == 0: # 榛樿绗竴涓浘鐗囧姞瀵瑰彿
- checkmark_label = add_checkmark_icon(thumb_label, pil_image)
- selected_labels.append(idx)
-
- # 灏哻heckmark_label淇濆瓨鍦ㄦ爣绛句腑锛屽悗缁偣鍑绘椂鍙互鍙傝��
- thumb_label.checkmark_label = checkmark_label
-
- # 鏇存柊鍒楁暟鍜岃鏁�
- col += 1
- if col >= max_col:
- col = 0
- row += 1
-
- # 鏇存柊Canvas鐨勬粴鍔ㄥ尯鍩�
- thumbnail_container.update_idletasks()
- canvas.config(scrollregion=canvas.bbox("all"))
-
-def toggle_checkmark(event, label, idx):
- """鍒囨崲鍕鹃�夌姸鎬�"""
- checkmark_label = label.checkmark_label
- # 濡傛灉宸茬粡鏈夊嬀閫夊浘鏍囷紝绉婚櫎瀹冿紱濡傛灉娌℃湁锛屾坊鍔犲畠
- if checkmark_label:
- # 绉婚櫎鍕鹃�夊浘鏍�
- if idx == 0 :
- return
- checkmark_label.destroy()
- label.checkmark_label = None
- # 浠庨�変腑鐨勬爣绛惧垪琛ㄤ腑绉婚櫎
- if idx in selected_labels:
- selected_labels.remove(idx)
- else:
- # 娣诲姞鍕鹃�夊浘鏍�
- if idx ==len(thumbnails)-1:
- return
- pil_image = Image.open(thumbnails[idx])
- checkmark_label = add_checkmark_icon(label, pil_image)
- label.checkmark_label = checkmark_label
- selected_labels.append(idx)
-
- #print(selected_labels)
-
-
-def add_checkmark_icon(thumb_label, pil_image):
- """鍦ㄥ浘鍍忎笂娣诲姞鍕鹃�夊浘鏍�"""
- checkmark = Image.open("checkmark.png") # 鍋囪浣犳湁涓�涓嬀閫夊浘鏍�
- checkmark = checkmark.resize((30, 30)) # 璋冩暣鍥炬爣澶у皬
- checkmark_photo = ImageTk.PhotoImage(checkmark)
-
- # 鍒涘缓涓�涓爣绛炬潵鏀剧疆鍕鹃�夊浘鏍�
- checkmark_label = tk.Label(thumb_label, image=checkmark_photo, bg='white', width=30, height=30)
- checkmark_label.image = checkmark_photo # 淇濇寔鍥炬爣鐨勫紩鐢�
- # 灏嗗嬀閫夊浘鏍囨斁鍦ㄧ缉鐣ュ浘鍙充笂瑙�
- checkmark_label.place(x=pil_image.width - 15, y=5, anchor="ne") # 纭繚鍥炬爣浣嶇疆鍦ㄥ彸涓婅
-
- return checkmark_label
-
-
-def show_large_image(image):
- # 鍒涘缓涓�涓柊鐨勭獥鍙f潵鏄剧ず澶у浘
- top = tk.Toplevel(root)
- top.title("Large Image")
-
- # 浣跨敤 PIL 鍒涘缓 Image 瀵硅薄
- image_pil = Image.fromarray(image)
- image_tk = ImageTk.PhotoImage(image_pil)
-
- # 鍦ㄦ柊绐楀彛涓樉绀哄浘鐗�
- label = tk.Label(top, image=image_tk)
- label.image = image_tk # 淇濇寔瀵瑰浘鐗囩殑寮曠敤
- label.pack()
-# 璺宠浆鍒版寚瀹氳繘搴�
-
-
-def on_progress_change(event):
- total_time = player.get_length() / 1000 # 瑙嗛鎬绘椂闀匡紙绉掞級
- new_time = (event.x / progress_bar.winfo_width()) * total_time # 璁$畻鏂扮殑鏃堕棿
- player.set_time(int(new_time * 1000)) # 璁剧疆鏂版椂闂达紙姣锛�
-
-
-player = vlc.MediaPlayer()
-player.event_manager().event_attach(
- vlc.EventType.MediaPlayerEndReached, on_playback_ended)
-
-canvas = Canvas(video_frame, width=1080, height=1920) # 璁剧疆Canvas澶у皬
-canvas.pack(side=tk.BOTTOM, pady=10) # Video player area under progress bar
-
-# 鍒濆鍖� VLC 鎾斁鍣�
-# Windows 浣跨敤 set_hwnd(embed.winfo_id())锛孡inux 浣跨敤 set_xwindow(embed.winfo_id())
-player.set_hwnd(canvas.winfo_id())
-
-
-# 瑙嗛杩涘害鏉�
-progress_var = tk.DoubleVar()
-progress_bar = ttk.Scale(video_frame, variable=progress_var,
- from_=0, to=100, orient="horizontal", length=800)
-progress_bar.pack(side=tk.BOTTOM, pady=10)
-
-# 缁戝畾杩涘害鏉$偣鍑讳簨浠讹紝璺宠浆鍒版寚瀹氭椂闂�
-progress_bar.bind("<ButtonRelease-1>", on_progress_change)
-
-update_progress()
-# 璁剧疆涓荤獥鍙�
-# Functions
-
-output_dir = ""
-
-def open_folder():
- global output_dir
- """Open folder and get all MP4 files"""
- folder = filedialog.askdirectory()
- if not folder:
- return
-
- global video_files
- video_files = []
- for root_dir, dirs, files in os.walk(folder):
- for file in files:
- if file.lower().endswith(".mp4"):
- video_files.append(os.path.join(root_dir, file))
-
- if video_files:
- messagebox.showinfo("Info", f"鏂囦欢鏁伴噺锛歿len(video_files)}")
-
- root.title("鏂囦欢澶癸細"+folder+ ",鏂囦欢鏁伴噺锛�"+str(len(video_files)))
- root.update() # 鍒锋柊鐣岄潰
- load_video(video_files[0])
-
- output_dir = os.path.join(folder, "ProcessResults")
- create_folders(output_dir)
- else:
- messagebox.showerror("Error", "娌℃湁鎵惧埌MP4鏂囦欢")
-
-
-def load_video(video_path):
- """Load video into the player and start playback"""
- global current_video_path, video_player
- current_video_path = video_path
- thumbnail_frame.pack_forget()
- video_frame.pack(side=tk.LEFT, padx=0)
- player.set_media(vlc.Media(current_video_path))
- player.play()
-
-
-def delete_video():
- """Delete current video and play the next"""
- global current_video_idx
- update_title_minus_one()
- if current_video_idx < len(video_files):
- os.remove(video_files[current_video_idx])
- current_video_idx += 1
- if current_video_idx < len(video_files):
- load_video(video_files[current_video_idx])
- else:
- messagebox.showinfo("Info", "澶勭悊瀹屾瘯锛�")
-
-
-def split_video():
- """Delete current video and play the next"""
- global current_video_idx
- update_title_minus_one()
- if current_video_idx < len(video_files):
- target_file = video_files[current_video_idx]
-
- save_hook_= save_hook.get() == 1
- save_music_= save_music.get() == 1
-
- cut_video_by_frames(save_hook_,save_music_,target_file,selected_labels,len(thumbnails),output_dir)
-
- current_video_idx += 1
- if current_video_idx < len(video_files):
- load_video(video_files[current_video_idx])
- else:
- messagebox.showinfo("Info", "澶勭悊瀹屾瘯锛�")
-
-def update_title_minus_one():
- current_title = root.title()
- parts = current_title.rsplit("锛�", 1)
- if len(parts) == 2 and parts[1].isdigit():
- new_count = int(parts[1]) - 1
- new_title = f"{parts[0]}锛歿new_count}"
- root.title(new_title)
- root.update()
-
-
-def get_filename_without_extension(video_path):
- # 鑾峰彇鏂囦欢鍚嶏紝鍘婚櫎璺緞
- filename_with_extension = os.path.basename(video_path)
- # 鍘婚櫎鎵╁睍鍚�
- filename_without_extension = os.path.splitext(filename_with_extension)[0]
- return filename_without_extension
-
-
-def cut_video_by_frames(save_hook,save_music,video_path, frame_segments, total_frames, output_dir):
- """
- 灏嗚棰戞寜鐓ф寚瀹氱殑甯у垏鐗囪繘琛屽垏鍓层��
-
- 鍙傛暟锛�
- - video_path: 杈撳叆瑙嗛鐨勮矾寰�
- - frame_segments: 鍒囩墖鐨勫抚搴忓彿鏁扮粍锛屼緥濡傦細[0, M1, M2, ..., Mlast]
- - output_dir: 杈撳嚭瑙嗛鏂囦欢鐨勭洰褰�
- """
- fps = 30 # default fps
- frame_segments.sort()
-
- # 鑾峰彇瑙嗛鐨勫抚鐜� (fps)
- command = [
- "ffmpeg", "-i", video_path, "-vf", "fps=1", "-f", "null", "-"
- ]
- result = subprocess.run(command, stdout=subprocess.PIPE,
- stderr=subprocess.PIPE, text=True, encoding='utf-8')
-
- if result.returncode != 0:
- print(f"Error occurred while executing the command: {result.stderr}")
- else:
- output = result.stderr
-
- if output:
- fps_line = next(line for line in output.splitlines() if 'fps' in line)
- # 浣跨敤姝e垯琛ㄨ揪寮忔彁鍙栧抚鐜囧�硷紙鍋囪fps鍊兼�绘槸鍑虹幇鍦�"fps"鍓嶉潰锛�
- match = re.search(r'(\d+(\.\d+)?)\s*fps', fps_line)
- if match:
- fps = float(match.group(1)) # 鎻愬彇骞惰浆鎹负 float
- print(f"FPS: {fps}")
- else:
- print("No output from ffmpeg")
-
-
- print(f"瑙嗛鐨勬�诲抚鏁�: {total_frames}, 甯х巼: {fps}")
-
- file_name_witout_extension = get_filename_without_extension(video_path)
-
- if save_music:
- output_file = os.path.join(os.path.join(output_dir,"music"), f"{file_name_witout_extension}.wav")
- command = ["ffmpeg", "-i", video_path, "-vn",
- "-acodec", "pcm_s16le","-ar", "44100","-ac", "2", output_file]
- subprocess.Popen(command)
-
- # 閬嶅巻鍒囩墖鍖洪棿
- for i in range(len(frame_segments) - 1):
- start_frame = frame_segments[i]
- end_frame = frame_segments[i + 1]
-
-
- start_time = float(start_frame) / fps
- end_time = float(end_frame) / fps
-
- if save_hook and i==0:
- output_file = os.path.join(os.path.join(output_dir,"hook"), f"{file_name_witout_extension}.mp4")
- else:
- output_file = os.path.join(os.path.join(output_dir,"slice"), f"{file_name_witout_extension}_{i + 1}.mp4")
-
-
- # 浣跨敤 FFmpeg 鍛戒护鏉ュ垏鍓茶棰�
- command = [
- "ffmpeg", "-i", video_path, "-ss", f"{start_time:.10f}", "-to", f"{end_time:.10f}",
- "-c:v", "libx264", "-crf", "18","-preset", "veryslow", output_file
- ]
- print(" ".join(command))
-
- subprocess.Popen(command)
-
- # 鏈�鍚庝竴娈靛鐞嗭紙浠庢渶鍚庝竴涓垏鐗囧埌瑙嗛缁撴潫锛�
- last_start_frame = frame_segments[-1]
- last_start_time = last_start_frame / fps
- output_file = os.path.join(
- os.path.join(output_dir,"slice"), f"{file_name_witout_extension}_{len(frame_segments)}.mp4")
-
- #print(f"姝e湪鍒囧壊鏈�鍚庝竴娈碉細浠� {last_start_time:.10f}s 鍒拌棰戠粨鏉燂紝淇濆瓨涓� {output_file}")
- command = [
- "ffmpeg", "-i", video_path, "-ss", f"{last_start_time:.10f}",
- "-c:v", "libx264","-crf", "18","-preset", "veryslow", output_file
- ]
- print(" ".join(command))
- subprocess.Popen(command)
-
-def create_folders(base_folder):
- """Create a folder structure for saving results"""
- hook_folder = os.path.join(base_folder, "hook")
- music_folder = os.path.join(base_folder, "music")
- category_folder = os.path.join(base_folder, "slice")
-
- if not os.path.exists(hook_folder):
- os.makedirs(hook_folder)
- if not os.path.exists(music_folder):
- os.makedirs(music_folder)
- if not os.path.exists(category_folder):
- os.makedirs(category_folder)
-
-
-# Buttons
-open_folder_button = tk.Button(control_frame, text="鎵撳紑鏂囦欢澶�", command=open_folder)
-open_folder_button.pack()
-
-# 鎾斁鎺у埗鎸夐挳锛堟挱鏀�/鏆傚仠锛�
-play_pause_button = tk.Button(control_frame, text="鏆傚仠瑙嗛", command=toggle_play_pause)
-play_pause_button.pack()
-
-delete_button = tk.Button(control_frame, text="涓嶄繚鐣�", command=delete_video)
-delete_button.pack()
-
-save_hook = tk.IntVar(value=1) # 榛樿鍕鹃��
-save_music = tk.IntVar(value=1) # 榛樿鍕鹃��
-
-# 鍒涘缓涓や釜 Checkbutton
-checkbox1 = tk.Checkbutton(control_frame, text="淇濆瓨Hook瑙嗛", variable=save_hook)
-checkbox1.pack()
-
-checkbox2 = tk.Checkbutton(control_frame, text="淇濆瓨闊抽", variable=save_music)
-checkbox2.pack()
-
-
-
-delete_button = tk.Button(control_frame, text="鎷嗗垎", command=split_video)
-delete_button.pack()
-
-
-menu_bar = tk.Menu(root)
-file_menu = tk.Menu(menu_bar, tearoff=0)
-file_menu.add_command(label="鎵撳紑鏂囦欢澶�", command=open_folder)
-menu_bar.add_cascade(label="鏂囦欢", menu=file_menu)
-root.config(menu=menu_bar)
-
-#video_frame.pack_forget()
-
-#display_thumbnails("E:\鎶栭煶-AI椋庢櫙\鏂板缓鏂囦欢澶筡_demoold")
-# Start the Tkinter loop
-root.mainloop()
diff --git a/video-splitor.py b/video-splitor.py
new file mode 100644
index 0000000..154b9c7
--- /dev/null
+++ b/video-splitor.py
@@ -0,0 +1,694 @@
+import tkinter as tk
+from tkinter import filedialog, messagebox, ttk, Canvas,PhotoImage
+import os
+import numpy as np
+from PIL import Image, ImageTk
+import vlc
+import subprocess
+import functools
+import cv2
+import threading
+from multiprocessing import Pool
+import time
+from threading import Thread
+from queue import Queue
+
+class LoopVlcPlayer:
+ def __init__(self, canvas):
+ self.player = vlc.Instance()
+ self.canvas = canvas
+
+ # 鍒涘缓濯掍綋鍒楄〃鎾斁鍣ㄥ拰濯掍綋鎾斁鍣�
+ self.listPlayer = self.player.media_list_player_new()
+ self.media_player = self.player.media_player_new()
+
+ # 缁戝畾 media_player 鍒� Canvas
+ self.media_player.set_hwnd(self.canvas.winfo_id()) # For Windows
+ # 濡傛灉杩愯鍦� MacOS 鎴� Linux锛岃鏍规嵁骞冲彴鏇挎崲缁戝畾鏂规硶锛�
+ # MacOS: self.media_player.set_nsobject(self.canvas.winfo_id())
+ # Linux: self.media_player.set_xwindow(self.canvas.winfo_id())
+ self.listPlayer.set_media_player(self.media_player)
+
+ def addPlaylist(self, local_path):
+ if not os.path.exists(local_path):
+ raise FileNotFoundError(f"The file {local_path} does not exist.")
+
+ self.media_list = self.player.media_list_new()
+ self.media_list.add_media(local_path)
+ self.listPlayer.set_media_list(self.media_list)
+ self.listPlayer.set_playback_mode(vlc.PlaybackMode.loop)
+
+ self.play()
+
+ def play(self):
+ # 鍚姩鎾斁
+ if self.media_list is None:
+ raise ValueError("No media added to the playlist. Use add_playlist() first.")
+ self.listPlayer.play()
+
+ def stop(self):
+ # 鍋滄鎾斁
+ self.listPlayer.stop()
+
+ def removePlaylist(self):
+ """
+ 鍋滄鎾斁骞堕噴鏀惧獟浣撳垪琛ㄨ祫婧愶紝鍏佽鏂囦欢鍦ㄧ‖浠朵笂琚叾浠栫▼搴忓垹闄ゃ��
+ """
+ if self.media_list:
+ self.stop()
+ self.media_list.release()
+ self.media_list = None # 閲婃斁寮曠敤浠ョ‘淇濇竻鐞嗙敓鏁�
+ print("Playlist removed and resources released.")
+
+
+# Global variables
+video_files = [] # List of video files
+current_video_idx = 0 # Index of the current video
+current_video_path = ""
+video_player = None
+thumbnail_images = []
+split_info = []
+
+# Create the main window
+root = tk.Tk()
+root.title("绠�鏄撹棰戞媶瑙e伐鍏� 0.1")
+root.state('zoomed') # Fullscreen
+
+screen_width = root.winfo_screenwidth()
+screen_height = root.winfo_screenheight()
+
+
+# Video playing frame
+video_frame = tk.Frame(root, width=1080, height=1920)
+video_frame.pack(side=tk.LEFT, padx=0)
+
+# Frame for thumbnail images
+thumbnail_frame = tk.Frame(root, width=1080, height=1920)
+thumbnail_frame.pack_forget()
+
+# Frame for right-side info and buttons
+control_frame = tk.Frame(root, width=60, height=200, bg="lightblue")
+control_frame.pack(side=tk.RIGHT, anchor="ne", padx=5, pady=5)
+
+
+
+selected_labels = [] # 璁板綍褰撳墠閫変腑鐨勬爣绛�
+file_frames = []
+file_fps = 0
+file_frame_count = 0
+file_width =0
+file_height = 0
+
+def display_thumbnails(video_file):
+ global selected_labels,file_frames,file_fps,file_frame_count,file_width,file_height
+ selected_labels = []
+ file_frames = []
+ file_fps = 0
+ file_frame_count = 0
+ file_width = 0
+ file_height =0
+
+ row, col = 0, 0
+ max_col = (screen_width - 100) // 90 - 1 # 鍔ㄦ�佸湴
+
+ # 鍒涘缓Canvas鍜屽瀭鐩存粴鍔ㄦ潯
+ thumbnail_frame.pack(side=tk.LEFT, padx=0)
+
+ canvas = tk.Canvas(thumbnail_frame, width=screen_width - 100, height=screen_height)
+ canvas.grid(row=0, column=0, sticky='nsew')
+
+ scrollbar = ttk.Scrollbar(thumbnail_frame, orient="vertical", command=canvas.yview)
+ scrollbar.grid(row=0, column=1, sticky='ns')
+
+ canvas.configure(yscrollcommand=scrollbar.set)
+
+ # 鍒涘缓涓�涓猣rame浣滀负Canvas鐨勫瓙椤规潵娣诲姞缂╃暐鍥�
+ thumbnail_container = tk.Frame(canvas)
+ canvas.create_window((0, 0), window=thumbnail_container, anchor="nw")
+
+ # 鍚敤榧犳爣婊氳疆浜嬩欢鏉ユ粴鍔–anvas
+ def on_mouse_wheel(event):
+ """澶勭悊榧犳爣婊氳疆浜嬩欢"""
+ canvas.yview_scroll(int(-1 * (event.delta / 120)), "units")
+
+ # 缁戝畾榧犳爣婊氳疆浜嬩欢
+ canvas.bind_all("<MouseWheel>", on_mouse_wheel)
+
+ """
+ 璇诲彇 MP4 瑙嗛骞跺皢姣忎竴甯у瓨鍌ㄥ埌鍐呭瓨涓�
+ """
+ def convert_cv_to_tk_image(cv_image):
+ """
+ 灏� OpenCV 鍥惧儚杞崲涓� Tkinter 鍙敤鐨勫浘鍍忔牸寮�
+ """
+ pil_image = Image.fromarray(cv2.cvtColor(cv_image, cv2.COLOR_BGR2RGB))
+ # 杞崲涓篢kinter鍙敤鐨凱hotoImage鏍煎紡
+ return ImageTk.PhotoImage(pil_image)
+
+ def get_thumbnail_width_height(width,height,max_size=120):
+ scale = min(max_size / height, max_size / width)
+ return int(width * scale),int(height * scale)
+
+ def add_label_to_contanier(idx,thumb,row,col):
+ thumb_label = tk.Label(thumbnail_container, image=thumb)
+ thumb_label.image = thumb # 蹇呴』淇濇寔瀵瑰浘鍍忕殑寮曠敤
+ thumb_label.grid(row=row, column=col, padx=1, pady=1)
+
+ # 灏唗oggle_checkmark鐨勮皟鐢ㄧ敤 functools.partial鍖呰锛屼紶閫抜dx
+ thumb_label.bind("<Button-1>", functools.partial(toggle_checkmark, label=thumb_label, idx=idx))
+
+ checkmark_label = None
+ if idx == 0: # 榛樿绗竴涓浘鐗囧姞瀵瑰彿
+ checkmark_label = add_checkmark_icon(thumb_label)
+ selected_labels.append(idx)
+ # 灏哻heckmark_label淇濆瓨鍦ㄦ爣绛句腑锛屽悗缁偣鍑绘椂鍙互鍙傝��
+ thumb_label.checkmark_label = checkmark_label
+ thumbnail_container.update()
+ thumbnail_container.update_idletasks()
+
+ cap = cv2.VideoCapture(video_file)
+ file_frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
+ file_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
+ file_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
+ thumbnail_width,thumbnail_height = get_thumbnail_width_height(file_width,file_height)
+ file_fps = cap.get(cv2.CAP_PROP_FPS)
+ frame_idx = 0
+ while True:
+ ret, frame = cap.read()
+ if not ret:
+ break
+ file_frames.append(frame)
+ add_label_to_contanier(frame_idx,convert_cv_to_tk_image(cv2.resize(frame, (thumbnail_width, thumbnail_height))),row,col)
+ frame_idx +=1
+ col += 1
+ if col >= max_col:
+ col = 0
+ row += 1
+
+ cap.release()
+ # 鏇存柊Canvas鐨勬粴鍔ㄥ尯鍩�
+ thumbnail_container.update_idletasks()
+ canvas.config(scrollregion=canvas.bbox("all"))
+
+def toggle_checkmark(event, label, idx):
+ """鍒囨崲鍕鹃�夌姸鎬�"""
+ checkmark_label = label.checkmark_label
+ # 濡傛灉宸茬粡鏈夊嬀閫夊浘鏍囷紝绉婚櫎瀹冿紱濡傛灉娌℃湁锛屾坊鍔犲畠
+ if checkmark_label:
+ # 绉婚櫎鍕鹃�夊浘鏍�
+ if idx == 0 :
+ return
+ checkmark_label.destroy()
+ label.checkmark_label = None
+ # 浠庨�変腑鐨勬爣绛惧垪琛ㄤ腑绉婚櫎
+ if idx in selected_labels:
+ selected_labels.remove(idx)
+ else:
+ # 娣诲姞鍕鹃�夊浘鏍�
+ if idx ==file_frame_count-1:
+ return
+ checkmark_label = add_checkmark_icon(label)
+ label.checkmark_label = checkmark_label
+ selected_labels.append(idx)
+
+ #print(selected_labels)
+
+
+def add_checkmark_icon(thumb_label):
+ """鍦ㄥ浘鍍忎笂娣诲姞鍕鹃�夊浘鏍�"""
+ checkmark = Image.open("checkmark.png") # 鍋囪浣犳湁涓�涓嬀閫夊浘鏍�
+ checkmark = checkmark.resize((30, 30)) # 璋冩暣鍥炬爣澶у皬
+ checkmark_photo = ImageTk.PhotoImage(checkmark)
+
+ # 鍒涘缓涓�涓爣绛炬潵鏀剧疆鍕鹃�夊浘鏍�
+ checkmark_label = tk.Label(thumb_label, image=checkmark_photo, bg='white', width=30, height=30)
+ checkmark_label.image = checkmark_photo # 淇濇寔鍥炬爣鐨勫紩鐢�
+ # 灏嗗嬀閫夊浘鏍囨斁鍦ㄧ缉鐣ュ浘鍙充笂瑙�
+ checkmark_label.place(x=80, y=5, anchor="ne") # 纭繚鍥炬爣浣嶇疆鍦ㄥ彸涓婅
+
+ return checkmark_label
+
+
+def show_large_image(image):
+ # 鍒涘缓涓�涓柊鐨勭獥鍙f潵鏄剧ず澶у浘
+ top = tk.Toplevel(root)
+ top.title("Large Image")
+
+ # 浣跨敤 PIL 鍒涘缓 Image 瀵硅薄
+ image_pil = Image.fromarray(image)
+ image_tk = ImageTk.PhotoImage(image_pil)
+
+ # 鍦ㄦ柊绐楀彛涓樉绀哄浘鐗�
+ label = tk.Label(top, image=image_tk)
+ label.image = image_tk # 淇濇寔瀵瑰浘鐗囩殑寮曠敤
+ label.pack()
+# 璺宠浆鍒版寚瀹氳繘搴�
+
+
+def on_progress_change(event):
+ global loopPlayer
+ total_time = loopPlayer.media_player.get_length() / 1000 # 瑙嗛鎬绘椂闀匡紙绉掞級
+ new_time = (event.x / progress_bar.winfo_width()) * total_time # 璁$畻鏂扮殑鏃堕棿
+ loopPlayer.media_player.set_time(int(new_time * 1000)) # 璁剧疆鏂版椂闂达紙姣锛�
+
+
+
+def use_video():
+ loopPlayer.stop()
+ video_frame.pack_forget()
+ display_thumbnails(current_video_path)
+
+
+def toggle_play_pause():
+ global loopPlayer
+ if loopPlayer.listPlayer.is_playing():
+ loopPlayer.listPlayer.pause() # 鏆傚仠鎾斁
+ play_pause_button.config(text="鎾斁瑙嗛") # 鏇存柊鎸夐挳鏂囨湰涓烘挱鏀�
+ else:
+ loopPlayer.listPlayer.play() # 鎾斁
+ play_pause_button.config(text="鏆傚仠瑙嗛") # 鏇存柊鎸夐挳鏂囨湰涓烘殏鍋�
+
+# 鏇存柊杩涘害鏉″苟澧炲姞璋冭瘯淇℃伅
+
+
+def update_progress():
+ # 纭繚鎾斁鍣ㄦ鍦ㄦ挱鏀�
+ global loopPlayer
+ if loopPlayer.media_player.is_playing():
+ current_time = loopPlayer.media_player.get_time() / 1000 # 姣杞负绉�
+ total_time = loopPlayer.media_player.get_length() / 1000 # 姣杞负绉�
+ if total_time > 0:
+ progress_percentage = (current_time / total_time) * 100
+ progress_var.set(progress_percentage)
+ progress_bar.after(10, update_progress)
+ else:
+ progress_bar.after(10, update_progress)
+
+
+# 瑙嗛杩涘害鏉�
+progress_var = tk.DoubleVar()
+progress_bar = ttk.Scale(video_frame, variable=progress_var,
+ from_=0, to=100, orient="horizontal", length=800)
+progress_bar.pack(side=tk.TOP, pady=10)
+
+canvas = Canvas(video_frame, width=1080, height=1920) # 璁剧疆Canvas澶у皬
+canvas.pack(side=tk.TOP) # Video player area under progress bar
+
+loopPlayer = LoopVlcPlayer(canvas)
+
+
+
+
+# 缁戝畾杩涘害鏉$偣鍑讳簨浠讹紝璺宠浆鍒版寚瀹氭椂闂�
+progress_bar.bind("<ButtonRelease-1>", on_progress_change)
+
+update_progress()
+# 璁剧疆涓荤獥鍙�
+# Functions
+
+output_dir = ""
+main_folder = ""
+
+def open_folder():
+ global output_dir,main_folder
+ """Open folder and get all MP4 files"""
+ main_folder = filedialog.askdirectory()
+ if not main_folder:
+ return
+
+ global video_files
+ video_files = []
+ for root_dir, dirs, files in os.walk(main_folder):
+ for file in files:
+ if file.lower().endswith(".mp4"):
+ video_files.append(os.path.join(root_dir, file))
+
+ if video_files:
+ messagebox.showinfo("Info", f"鏂囦欢鏁伴噺锛歿len(video_files)}")
+
+ root.title("鏂囦欢澶癸細"+main_folder+ ",鏂囦欢鏁伴噺锛�"+str(len(video_files)))
+ root.update() # 鍒锋柊鐣岄潰
+ load_video(video_files[0])
+
+ output_dir = os.path.join(main_folder, "ProcessResults")
+ create_folders(output_dir)
+ else:
+ messagebox.showerror("Error", "娌℃湁鎵惧埌MP4鏂囦欢")
+
+
+def load_video(video_path):
+ global loopPlayer
+ """Load video into the player and start playback"""
+ global current_video_path, video_player
+ update_title_add_file_path(video_path)
+ current_video_path = video_path
+ thumbnail_frame.pack_forget()
+ video_frame.pack(side=tk.LEFT, padx=0)
+ loopPlayer.addPlaylist(current_video_path)
+ loopPlayer.play()
+
+
+
+def delete_video():
+ """Delete current video and play the next"""
+ global current_video_idx
+ loopPlayer.removePlaylist()
+ update_title_minus_one()
+ if current_video_idx < len(video_files):
+ os.remove(video_files[current_video_idx])
+ current_video_idx += 1
+ if current_video_idx < len(video_files):
+ load_video(video_files[current_video_idx])
+ else:
+ messagebox.showinfo("Info", "澶勭悊瀹屾瘯锛�")
+
+
+
+def save_video_slice(fps,width,height,frames_to_save, output_file):
+ """
+ 鏍规嵁鎸囧畾鐨勫抚鑼冨洿灏嗚棰戜繚瀛樹负鏂扮殑鐗囨
+ """
+ fourcc = cv2.VideoWriter_fourcc(*'mp4v') # 鐢ㄤ簬鐢熸垚 MP4 鏍煎紡
+ #cv2.VideoWriter_fourcc(*'H264')
+ #cv2.VideoWriter_fourcc(*'avc1')
+ #cv2.VideoWriter_fourcc(*'mp4v')
+ out = cv2.VideoWriter(output_file, fourcc, fps, (width, height))
+
+ # 閬嶅巻鎸囧畾鑼冨洿鐨勫抚骞跺啓鍏ュ埌鏂拌棰戜腑
+ for frame in frames_to_save:
+ out.write(frame)
+ out.release()
+
+def save_slice_in_thread(fps, width, height, frames, output_file):
+ save_video_slice(fps, width, height, frames, output_file)
+
+
+def process_video_slices(save_hook,output_dir,file_basename):
+ """
+ 骞跺彂澶勭悊澶氫釜瑙嗛鍒囩墖骞跺啓鍏ユ枃浠躲��
+
+ 鍙傛暟锛�
+ - frames: 宸插姞杞界殑鎵�鏈夎棰戝抚
+ - slice_ranges: 姣忎釜鍒囩墖鐨勫抚鑼冨洿 [(start1, end1), (start2, end2), ...]
+ - output_dir: 杈撳嚭瑙嗛鍒囩墖淇濆瓨鐨勭洰褰�
+ - fps: 甯х巼
+ - width: 瑙嗛瀹藉害
+ - height: 瑙嗛楂樺害
+ """
+ global file_frame_count,file_fps,file_width,file_height,selected_labels,file_frames
+
+ def convert_to_ranges(frame_segments, total_frames):
+ ranges = []
+ for i in range(len(frame_segments) - 1):
+ start_frame = frame_segments[i]
+ end_frame = frame_segments[i + 1] - 1 # 涓嶅寘鍚玡nd_frame
+ ranges.append([start_frame, end_frame])
+
+ # 澶勭悊鏈�鍚庝竴娈�
+ last_start_frame = frame_segments[-1]
+ ranges.append([last_start_frame, total_frames]) # 鏈�鍚庝竴娈电洿鍒拌棰戠粨鏉�
+ return ranges
+
+ slice_ranges = convert_to_ranges(selected_labels,file_frame_count)
+
+ threads = []
+ for i, slice_range in enumerate(slice_ranges):
+ # 璁剧疆杈撳嚭璺緞
+ if save_hook and i == 0:
+ output_file = os.path.join(os.path.join(output_dir, "hook"), f"{file_basename}.mp4")
+ else:
+ output_file = os.path.join(os.path.join(output_dir, "slice"), f"{file_basename}_{i + 1}.mp4")
+
+ slice_frames = file_frames[slice_range[0]:slice_range[1]]
+ t = threading.Thread(target=save_slice_in_thread, args=(file_fps, file_width, file_height, slice_frames, output_file))
+ threads.append(t)
+ t.start()
+
+ # 鍙�夛細绛夊緟鎵�鏈夌嚎绋嬪畬鎴�
+ #for t in threads:
+ # t.join()
+
+
+
+
+
+ # 鍒涘缓绾跨▼姹�
+ '''
+ with ThreadPoolExecutor() as executor:
+ futures = []
+ for i, slice_range in enumerate(slice_ranges):
+ # 璁剧疆杈撳嚭璺緞
+ if save_hook and i == 0:
+ output_file = os.path.join(os.path.join(output_dir, "hook"), f"{file_basename}_{i + 1}.mp4")
+ else:
+ output_file = os.path.join(os.path.join(output_dir, "slice"), f"{file_basename}_{i + 1}.mp4")
+
+ # 鎻愪氦浠诲姟鍒扮嚎绋嬫睜
+ futures.append(executor.submit(save_video_slice, slice_range, output_file))
+
+ # 绛夊緟鎵�鏈変换鍔″畬鎴�
+ for future in futures:
+ future.result() # 鑾峰彇缁撴灉锛堝鏈夊紓甯镐細鍦ㄨ繖閲屾姏鍑猴級
+ '''
+ '''
+ for i, slice_range in enumerate(slice_ranges):
+ if save_hook and i==0:
+ output_file = os.path.join(os.path.join(output_dir,"hook"), f"{file_basename}_{i+1}.mp4")
+ else:
+ output_file = os.path.join(os.path.join(output_dir,"slice"), f"{file_basename}_{i+1}.mp4")
+ save_video_slice(file_fps, file_width, file_height,file_frames[slice_range[0]:slice_range[1]], output_file)
+ '''
+
+
+
+def split_video():
+ """Delete current video and play the next"""
+ global current_video_idx
+ print(selected_labels)
+ update_title_minus_one()
+ if current_video_idx < len(video_files):
+ target_file = video_files[current_video_idx]
+
+ save_hook_= save_hook.get() == 1
+ save_music_= save_music.get() == 1
+ save_music_without_hook_ = save_music_without_hook.get() == 1
+
+ cut_video_by_frames(save_hook_,save_music_,save_music_without_hook_,target_file,selected_labels,file_frame_count,output_dir)
+
+ current_video_idx += 1
+ if current_video_idx < len(video_files):
+ load_video(video_files[current_video_idx])
+ else:
+ messagebox.showinfo("Info", "澶勭悊瀹屾垚锛�")
+ thumbnail_frame.pack_forget()
+
+def even_split_video():
+ """Delete current video and play the next"""
+ global current_video_idx,file_frame_count,output_dir
+ loopPlayer.stop()
+ update_title_minus_one()
+ if current_video_idx < len(video_files):
+ target_file = video_files[current_video_idx]
+
+ even_split_count_= scale_progress_var.get()
+ scale_save_music_ = scale_save_music.get() == 1
+
+ even_cut_video_by_frames(even_split_count_,scale_save_music_,target_file,output_dir)
+
+ current_video_idx += 1
+ if current_video_idx < len(video_files):
+ load_video(video_files[current_video_idx])
+ else:
+ messagebox.showinfo("Info", "澶勭悊瀹屾垚锛�")
+ thumbnail_frame.pack_forget()
+
+
+
+def update_title_minus_one():
+ root.title("鏂囦欢澶癸細"+main_folder+ ",鏂囦欢鏁伴噺锛�"+str(len(video_files)-current_video_idx))
+ root.update()
+
+def update_title_add_file_path(file_path):
+ root.title("鏂囦欢澶癸細"+main_folder+ ",鏂囦欢鏁伴噺锛�<"+str(len(video_files)-current_video_idx)+">."+file_path)
+ root.update()
+
+def get_filename_without_extension(video_path):
+ # 鑾峰彇鏂囦欢鍚嶏紝鍘婚櫎璺緞
+ filename_with_extension = os.path.basename(video_path)
+ # 鍘婚櫎鎵╁睍鍚�
+ filename_without_extension = os.path.splitext(filename_with_extension)[0]
+ return filename_without_extension
+
+def even_cut_video_by_frames(even_split_count_,scale_save_music_,video_path,output_dir):
+ """
+ 灏嗚棰戞寜鐓у浐瀹氶棿闅旇繘琛屽钩鍧囧垏鍓层��
+ - output_dir: 杈撳嚭瑙嗛鏂囦欢鐨勭洰褰�
+ """
+ global file_fps,file_frame_count,file_frames,file_width,file_height
+
+ def split_video_into_slices(total_count, split_count_):
+ # 濡傛灉瑙嗛甯ф暟灏忎簬绛変簬鍒嗙墖鏁帮紝鍒欎笉鎷嗗垎
+ if total_count <= split_count_:
+ return [(0, total_count)] # 杩斿洖涓�涓寘鍚暣涓棰戠殑鍒囩墖
+ # 璁$畻闇�瑕佺殑鍒囩墖鏁伴噺
+ slice_count = total_count // split_count_ # 鍩烘湰鐨勫垏鐗囨暟閲�
+ remaining_frames = total_count % split_count_ # 鍓╀綑鐨勫抚鏁�
+
+ slices = []
+ # 鍒涘缓姣忎釜鍒囩墖
+ for i in range(int(slice_count)):
+ start_frame = int(i * split_count_)
+ end_frame = int((i + 1) * split_count_)
+ slices.append((start_frame, end_frame))
+ # 濡傛灉鏈夊墿浣欑殑甯э紝灏嗗叾浣滀负鏈�鍚庝竴涓垏鐗�
+ if remaining_frames > 0:
+ slices.append((int(slice_count * split_count_), int(slice_count * split_count_ + remaining_frames)))
+ return slices
+
+ if file_frame_count ==0 :
+ cap = cv2.VideoCapture(video_path)
+ file_frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
+ file_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
+ file_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
+ file_fps = cap.get(cv2.CAP_PROP_FPS)
+ while True:
+ ret, frame = cap.read()
+ if not ret:
+ break
+ file_frames.append(frame)
+ cap.release()
+
+ file_name_witout_extension = get_filename_without_extension(video_path)
+ if scale_save_music_:
+ output_file = os.path.join(os.path.join(output_dir,"music"), f"{file_name_witout_extension}.wav")
+ command = ["ffmpeg", "-i", video_path, "-vn", "-acodec", "pcm_s16le","-ar", "44100","-ac", "2", output_file]
+ print(" ".join(command))
+ subprocess.Popen(command)
+
+ slice_ranges = split_video_into_slices(file_frame_count,even_split_count_)
+ print("even_slice_ranges")
+ print(slice_ranges)
+
+ threads = []
+ for i, slice_range in enumerate(slice_ranges):
+ output_file = os.path.join(os.path.join(output_dir, "slice"), f"{file_name_witout_extension}_{i + 1}.mp4")
+ slice_frames = file_frames[slice_range[0]:slice_range[1]]
+ t = threading.Thread(target=save_slice_in_thread, args=(file_fps, file_width, file_height, slice_frames, output_file))
+ threads.append(t)
+ t.start()
+
+ # 鍙�夛細绛夊緟鎵�鏈夌嚎绋嬪畬鎴�
+ #for t in threads:
+ # t.join()
+
+
+def cut_video_by_frames(save_hook,save_music,save_music_without_hook,video_path, frame_segments, total_frames, output_dir):
+ """
+ 灏嗚棰戞寜鐓ф寚瀹氱殑甯у垏鐗囪繘琛屽垏鍓层��
+
+ 鍙傛暟锛�
+ - video_path: 杈撳叆瑙嗛鐨勮矾寰�
+ - frame_segments: 鍒囩墖鐨勫抚搴忓彿鏁扮粍锛屼緥濡傦細[0, M1, M2, ..., Mlast]
+ - output_dir: 杈撳嚭瑙嗛鏂囦欢鐨勭洰褰�
+ """
+ global file_fps
+ frame_segments.sort()
+ file_name_witout_extension = get_filename_without_extension(video_path)
+
+ if save_music:
+ output_file = os.path.join(os.path.join(output_dir,"music"), f"{file_name_witout_extension}.wav")
+ if save_music_without_hook:
+ music_start_time = float(frame_segments[1]) / file_fps
+ command = ["ffmpeg", "-i", video_path, "-ss", str(music_start_time), "-vn", "-acodec", "pcm_s16le","-ar", "44100","-ac", "2", output_file]
+ print(" ".join(command))
+ else:
+ command = ["ffmpeg", "-i", video_path, "-vn", "-acodec", "pcm_s16le","-ar", "44100","-ac", "2", output_file]
+ print(" ".join(command))
+ subprocess.Popen(command)
+ if save_hook:
+ output_file = os.path.join(os.path.join(output_dir,"hook"), f"{file_name_witout_extension}.wav")
+ music_start_time = float(frame_segments[1]) / file_fps
+ command = ["ffmpeg", "-i", video_path, "-t", str(music_start_time), "-vn", "-acodec", "pcm_s16le", "-ar", "44100", "-ac", "2", output_file]
+ print(" ".join(command))
+ subprocess.Popen(command)
+
+ process_video_slices(save_hook,output_dir,file_name_witout_extension)
+
+
+
+
+def create_folders(base_folder):
+ """Create a folder structure for saving results"""
+ hook_folder = os.path.join(base_folder, "hook")
+ music_folder = os.path.join(base_folder, "music")
+ category_folder = os.path.join(base_folder, "slice")
+
+ if not os.path.exists(hook_folder):
+ os.makedirs(hook_folder)
+ if not os.path.exists(music_folder):
+ os.makedirs(music_folder)
+ if not os.path.exists(category_folder):
+ os.makedirs(category_folder)
+
+
+# Buttons
+open_folder_button = tk.Button(control_frame, text="鎵撳紑鏂囦欢澶�", command=open_folder,width=30)
+open_folder_button.pack(pady=5)
+
+# 鎾斁鎺у埗鎸夐挳锛堟挱鏀�/鏆傚仠锛�
+play_pause_button = tk.Button(control_frame, text="鏆傚仠瑙嗛", command=toggle_play_pause,width=30)
+play_pause_button.pack(pady=30)
+
+
+delete_button = tk.Button(control_frame, text="淇濈暀", command=use_video,width=30,bg="green")
+delete_button.pack(pady=10)
+
+delete_button = tk.Button(control_frame, text="涓嶄繚鐣�", command=delete_video,width=30,bg="red")
+delete_button.pack()
+
+save_hook = tk.IntVar(value=1) # 榛樿鍕鹃��
+save_music = tk.IntVar(value=1) # 榛樿鍕鹃��
+save_music_without_hook = tk.IntVar(value=1)
+
+# 鍒涘缓涓や釜 Checkbutton
+checkbox1 = tk.Checkbutton(control_frame, text="淇濆瓨Hook瑙嗛", variable=save_hook,width=30)
+checkbox1.pack(pady=30)
+
+checkbox2 = tk.Checkbutton(control_frame, text="淇濆瓨闊抽", variable=save_music,width=30)
+checkbox2.pack()
+
+checkbox3 = tk.Checkbutton(control_frame, text="闊抽(闄ook闊抽)", variable=save_music_without_hook,width=30)
+checkbox3.pack()
+
+
+delete_button = tk.Button(control_frame, text="鐢婚潰鎷嗗垎", command=split_video,width=30)
+delete_button.pack(pady=50)
+
+
+def _on_scale_progress_change(value):
+ # 闄愬埗杩涘害鏉$殑鍊间负10銆�20銆�30銆�40銆�50
+ rounded_value = round(float(value) / 5) * 5
+ scale_progress_var.set(rounded_value) # 璁剧疆鍥炶繘搴︽潯
+scale_progress_var = tk.DoubleVar()
+scale_progress_bar = tk.Scale(control_frame, variable=scale_progress_var, from_=10, to=50, orient="horizontal", length=300,
+ tickinterval=10, showvalue=True, sliderlength=30)
+scale_progress_bar.pack(pady=30)
+scale_progress_bar.set(20)
+
+scale_save_music = tk.IntVar(value=1) # 榛樿鍕鹃��
+checkbox4 = tk.Checkbutton(control_frame, text="淇濆瓨闊抽", variable=scale_save_music,width=30)
+checkbox4.pack(pady=5)
+
+even_split_button = tk.Button(control_frame, text="骞冲潎鎷嗗垎", command=even_split_video,width=30)
+even_split_button.pack(pady=5)
+
+
+'''
+menu_bar = tk.Menu(root)
+file_menu = tk.Menu(menu_bar, tearoff=0)
+file_menu.add_command(label="鎵撳紑鏂囦欢澶�", command=open_folder)
+menu_bar.add_cascade(label="鏂囦欢", menu=file_menu)
+root.config(menu=menu_bar)
+'''
+
+root.mainloop()
diff --git a/videosplitorV0.1.spec b/videosplitorV0.1.spec
index ee534d0..ba98d2c 100644
--- a/videosplitorV0.1.spec
+++ b/videosplitorV0.1.spec
@@ -3,9 +3,11 @@
import os
import shutil
from PyInstaller.utils.hooks import collect_all
+import zipfile
+import time
a = Analysis(
- ['tkv.py'],
+ ['video-splitor.py'],
pathex=[],
binaries=[],
datas=[],
@@ -43,21 +45,14 @@
# 瀹氫箟棰濆鎷疯礉鐨勬枃浠�
path_ffmpeg = os.path.join(os.getcwd(), 'ffmpeg.exe')
-path_thumb = os.path.join(os.getcwd(), 'mp4_generate_thumbnails.bat')
path_checkmark = os.path.join(os.getcwd(), 'checkmark.png')
-path_libvlc = os.path.join(os.getcwd(), 'libvlc.dll')
-path_libvlccore = os.path.join(os.getcwd(), 'libvlccore.dll')
-
-plugins_path = os.path.join(os.getcwd(), 'plugins')
+path_vlc_plugins = os.path.join(os.getcwd(), 'VLC.zip')
# 灏� ffmpeg.exe 鍜� plugins 鏂囦欢澶规坊鍔犲埌 EXE 鐨勫悓绾х洰褰�
datas = [
(path_ffmpeg, '.'),
- (path_thumb, '.'),
- (path_checkmark, '.'),
- (path_libvlc, '.'),
- (path_libvlccore, '.'),
- (plugins_path, 'plugins')
+ (path_checkmark, '.'),
+ (path_vlc_plugins, '.')
]
@@ -67,27 +62,18 @@
# 鑾峰彇鐢熸垚鐨� dist 鐩綍
dist_dir = os.path.join(os.getcwd(), 'dist')
- # 閫掑綊鎷疯礉 plugins 鐩綍
- if os.path.exists(plugins_path):
- destination_plugins = os.path.join(dist_dir, 'plugins')
- shutil.copytree(plugins_path, destination_plugins)
-
if os.path.exists(path_ffmpeg):
shutil.copy(path_ffmpeg, dist_dir)
- if os.path.exists(path_thumb):
- shutil.copy(path_thumb, dist_dir)
-
if os.path.exists(path_checkmark):
shutil.copy(path_checkmark, dist_dir)
-
- if os.path.exists(path_libvlc):
- shutil.copy(path_libvlc, dist_dir)
-
- if os.path.exists(path_libvlccore):
- shutil.copy(path_libvlccore, dist_dir)
+
+ if os.path.exists(path_vlc_plugins):
+ copied_file_path = shutil.copy(path_vlc_plugins, dist_dir)
+ with zipfile.ZipFile(copied_file_path, 'r') as zip_ref:
+ zip_ref.extractall(dist_dir)
+ time.sleep(1) # 绛夊緟璧勬簮閲婃斁
+ os.remove(copied_file_path)
# 鍦ㄦ墦鍖呭悗鐨勫簲鐢ㄤ腑鎵ц鏂囦欢鎷疯礉鎿嶄綔
-post_processing_hook(exe)
-
-
+post_processing_hook(exe)
\ No newline at end of file
--
Gitblit v1.9.1