python可视化拖拽分割长视频为多段小视频代码
代码语言:python
所属分类:其他
代码描述:python可视化拖拽分割长视频为多段小视频代码,可 平均切分,可拖拽调整,可预览分段视频,最后导出每个分段。
代码标签: python 可视化 拖拽 分割 长 视频 多段 小视频 代码
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
# -*- coding: utf-8 -*-
import sys
import os
import re
import shutil
import subprocess
from pathlib import Path
from PySide6.QtCore import Qt, Signal, QThread, QUrl, QRect, QPoint, QTimer
from PySide6.QtGui import QColor, QPainter, QPen, QBrush
from PySide6.QtWidgets import (
QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
QPushButton, QLabel, QSlider, QLineEdit, QTableWidget, QTableWidgetItem,
QHeaderView, QAbstractItemView, QGroupBox, QComboBox, QFileDialog,
QMessageBox, QSizePolicy, QInputDialog
)
from PySide6.QtMultimedia import QMediaPlayer, QAudioOutput
from PySide6.QtMultimediaWidgets import QVideoWidget
def get_ffmpeg_exe():
"""
优先使用系统 ffmpeg。
如果没有,则尝试使用 imageio_ffmpeg 提供的 ffmpeg。
"""
exe = shutil.which("ffmpeg")
if exe:
return exe
try:
import imageio_ffmpeg
return imageio_ffmpeg.get_ffmpeg_exe()
except Exception:
return None
def format_ms(ms):
"""把毫秒格式化为可读时间。"""
if ms is None:
ms = 0
ms = int(max(0, ms))
total_seconds = ms // 1000
milli = ms % 1000
h = total_seconds // 3600
m = (total_seconds % 3600) // 60
s = total_seconds % 60
if h > 0:
return f"{h:02d}:{m:02d}:{s:02d}.{milli:03d}"
return f"{m:02d}:{s:02d}.{milli:03d}"
def sanitize_filename(name):
"""清理文件名中的非法字符。"""
name = str(name).strip()
name = re.sub(r'[\\/:*?"<>|\r\n\t]+', "_", name)
name = name.strip().strip(".")
return name or "segment"
def make_unique_path(directory, base, ext):
"""生成不重名的输出文件路径。"""
os.makedirs(directory, exist_ok=True)
path = os.path.join(directory, f"{base}{ext}")
idx = 1
while os.path.exists(path):
path = os.path.join(directory, f"{base}_{idx}{ext}")
idx += 1
return path
class ExportWorker(QThread):
"""
后台导出线程,避免导出时界面卡死。
"""
status = Signal(str)
done = Signal(bool, str)
def __init__(self, jobs, parent=None):
super().__init__(parent)
self.jobs = jobs
def run(self):
messages = []
ok = True
total = len(self.jobs)
for idx, (output_path, cmd) in enumerate(self.jobs, 1):
self.status.emit(f"正在导出 {idx}/{total}: {os.path.basename(output_path)}")
try:
proc = subprocess.run(
cmd,
stdout=subprocess.DEVNULL,
stderr=subprocess.PIPE
)
err = ""
if proc.stderr:
err = proc.stderr.decode("utf-8", "ignore")
if proc.returncode == 0:
messages.append(f"成功: {output_path}")
else:
ok = False
messages.append(f"失败: {output_path}\n{err[-3000:]}")
except Exception as e:
ok = False
messages.append(f"失败: {output_path}\n{str(e)}")
self.done.emit(ok, "\n\n".join(messages) if messages else "没有导出任务")
class TimelineRangeWidget(QWidget):
"""
可视化时间线控件:
- 空白处拖拽:新建选区
- 左右手柄拖拽:调整开始/结束
- 选中区域拖拽:整体移动选区
- 空白处单击:定位播放位置
"""
rangeChanged = Signal(int, int)
seekRequested = Signal(int)
def __init__(self, parent=None):
super().__init__(parent)
self._duration = 0
self._start = 0
self._end = 0
self._position = 0
self._handle_w = 12
self._padding = 16
self._track_height = 26
self._min_range_ms = 200
self._drag_mode = None
self._drag_offset_ms = 0
self._press_ms = 0
self._anchor_ms = 0
self._moved = False
self._press_pos = QPoint()
self._orig_start = 0
self._orig_end = 0
self.setMinimumHeight(72)
self.setMouseTracking(True)
def duration(self):
return self._duration
def setDuration(self, ms):
ms = int(max(0, ms))
if ms == self._duration:
return
self._duration = ms
if self._end <= 0 or self._end > ms:
.........完整代码请登录后点击上方下载按钮下载查看














网友评论0