#!/usr/bin/env python3 import sys import os import subprocess from PyQt6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QPushButton, QFileDialog, QLabel, QLineEdit, QProgressBar) from PyQt6.QtCore import QThread, pyqtSignal class SplitWorker(QThread): progress = pyqtSignal(str) finished = pyqtSignal() def __init__(self, input_file, size_limit_mb, output_dir): super().__init__() self.input_file = input_file self.size_limit = size_limit_mb * 1000000 # Convert MB to bytes self.output_dir = output_dir def run(self): # Extract basename and set output pattern basename = os.path.splitext(os.path.basename(self.input_file))[0] output_pattern = os.path.join(self.output_dir, f"{basename}-%d.mp4") # Get total duration duration_cmd = [ "ffprobe", "-i", self.input_file, "-show_entries", "format=duration", "-v", "quiet", "-of", "default=noprint_wrappers=1:nokey=1" ] duration = float(subprocess.check_output(duration_cmd).decode().strip().split(".")[0]) cur_duration = 0 i = 1 while cur_duration < duration: output_file = os.path.join(self.output_dir, f"{basename}-{i}.mp4") ffmpeg_cmd = [ "ffmpeg", "-ss", str(cur_duration), "-i", self.input_file, "-fs", str(self.size_limit), "-c", "copy", "-y", output_file ] subprocess.run(ffmpeg_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # Get duration of the new chunk new_duration_cmd = [ "ffprobe", "-i", output_file, "-show_entries", "format=duration", "-v", "quiet", "-of", "default=noprint_wrappers=1:nokey=1" ] new_duration = float(subprocess.check_output(new_duration_cmd).decode().strip().split(".")[0]) cur_duration += new_duration self.progress.emit(f"Created chunk {i} ({cur_duration}/{duration} seconds processed)") i += 1 self.finished.emit() class VideoSplitterGUI(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("Video Splitter") self.setGeometry(100, 100, 400, 300) # Main widget and layout widget = QWidget() self.setCentralWidget(widget) layout = QVBoxLayout() widget.setLayout(layout) # Input file selection self.input_label = QLabel("No file selected") self.select_input_btn = QPushButton("Select MP4 File") self.select_input_btn.clicked.connect(self.select_input_file) layout.addWidget(self.input_label) layout.addWidget(self.select_input_btn) # Size limit input (in MB) self.size_label = QLabel("Chunk Size (MB):") self.size_input = QLineEdit("110") # Default 110 MB layout.addWidget(self.size_label) layout.addWidget(self.size_input) # Output directory selection self.output_label = QLabel("Output Directory: Current directory") self.select_output_btn = QPushButton("Select Output Directory") self.select_output_btn.clicked.connect(self.select_output_dir) layout.addWidget(self.output_label) layout.addWidget(self.select_output_btn) # Start button self.start_btn = QPushButton("Start Splitting") self.start_btn.clicked.connect(self.start_splitting) layout.addWidget(self.start_btn) # Progress self.progress_label = QLabel("Ready") self.progress_bar = QProgressBar() self.progress_bar.setMinimum(0) self.progress_bar.setMaximum(100) layout.addWidget(self.progress_label) layout.addWidget(self.progress_bar) # Stretch to push content up layout.addStretch() # Variables self.input_file = "" self.output_dir = os.getcwd() def select_input_file(self): file, _ = QFileDialog.getOpenFileName(self, "Select MP4 File", "", "MP4 Files (*.mp4)") if file: self.input_file = file self.input_label.setText(f"Selected: {os.path.basename(file)}") def select_output_dir(self): dir = QFileDialog.getExistingDirectory(self, "Select Output Directory") if dir: self.output_dir = dir self.output_label.setText(f"Output Directory: {dir}") def start_splitting(self): if not self.input_file: self.progress_label.setText("Error: No input file selected") return size_limit_mb = self.size_input.text() try: size_limit_mb = float(size_limit_mb) # Allow decimals like 110.5 MB if size_limit_mb <= 0: raise ValueError except ValueError: self.progress_label.setText("Error: Invalid size limit (must be a positive number)") return self.start_btn.setEnabled(False) self.progress_label.setText("Splitting in progress...") self.worker = SplitWorker(self.input_file, size_limit_mb, self.output_dir) self.worker.progress.connect(self.update_progress) self.worker.finished.connect(self.split_finished) self.worker.start() def update_progress(self, message): self.progress_label.setText(message) # Simple progress approximation (could be enhanced with actual file size checks) self.progress_bar.setValue(self.progress_bar.value() + 10) def split_finished(self): self.progress_label.setText("Splitting complete!") self.progress_bar.setValue(100) self.start_btn.setEnabled(True) if __name__ == "__main__": app = QApplication(sys.argv) window = VideoSplitterGUI() window.show() sys.exit(app.exec())