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