最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python進行批量剪輯視頻片頭片尾

 更新時間:2025年01月09日 10:37:51   作者:黑客白澤  
這篇文章主要為大家詳細介紹了如何使用Python進行批量剪輯視頻片頭片尾功能,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下

1.簡介

批量剪輯片頭片尾的軟件,讓你的視頻創(chuàng)作事半功倍,視頻剪輯處理完成后,用戶可以在指定文件夾中查看已經(jīng)剪切完片頭片尾的視頻‌。這些工具不僅適用于個人用戶進行日常的視頻編輯工作,也適合視頻制作團隊在項目制作中提高工作效率。

功能:

加載和保存配置:讀取和保存配置文件。

獲取視頻時長:使用ffprobe獲取視頻的總時長。

視頻剪輯:使用ffmpeg截取視頻片段,支持批量處理。

圖形用戶界面:通過tkinter選擇輸入文件和輸出目錄,設置開始和結(jié)束時間。

語音提示:在剪輯完成后進行語音提示。

2.運行效果

3.相關(guān)源碼

import os
import subprocess
import threading
import tkinter as tk
from tkinter import filedialog
from tkinter import messagebox
from tkinter import ttk
import json
from datetime import datetime, timedelta
import pyttsx3
 
INTERNAL_FOLDER = os.path.join(os.path.dirname(__file__), '_internal')
CONFIG_FILE = os.path.join(INTERNAL_FOLDER, 'config.json')
FFMPEG_FOLDER = os.path.join(INTERNAL_FOLDER, 'ffmpeg_folder')
COMPLETION_FILE = os.path.join(INTERNAL_FOLDER, 'completed.txt')
ICON_PATH = os.path.join(INTERNAL_FOLDER, 'moviecamera.ico')  # 使用_internal文件夾中的圖標
 
def ensure_internal_dir_exists():
    if not os.path.exists(INTERNAL_FOLDER):
        os.makedirs(INTERNAL_FOLDER)
 
def load_config():
    if os.path.exists(CONFIG_FILE):
        with open(CONFIG_FILE, 'r', encoding='utf-8') as f:
            return json.load(f)
    return {}
 
def save_config(config):
    ensure_internal_dir_exists()
    with open(CONFIG_FILE, 'w', encoding='utf-8') as f:
        json.dump(config, f)
 
def format_time(hours, minutes, seconds, milliseconds):
    return f"{int(hours):02}:{int(minutes):02}:{int(seconds):02}.{int(milliseconds):03}"
 
def get_video_duration(input_path):
    ffprobe_path = os.path.join(FFMPEG_FOLDER, 'ffprobe.exe')
    if not os.path.exists(ffprobe_path):
        messagebox.showerror("錯誤", "找不到 ffprobe 可執(zhí)行文件")
        return 0
    result = subprocess.run(
        [ffprobe_path, "-v", "error", "-show_entries", "format=duration", "-of", "default=noprint_wrappers=1:nokey=1", input_path],
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        universal_newlines=True
    )
    try:
        return float(result.stdout)
    except ValueError:
        print("FFprobe輸出:", result.stdout)  # 打印ffprobe標準輸出以便調(diào)試
        print("FFprobe錯誤:", result.stderr)  # 打印ffprobe錯誤輸出以便調(diào)試
        messagebox.showerror("錯誤", "無法獲取視頻時長,請檢查輸入文件")
        return 0
 
def trim_video(input_path, output_path, start_time, end_time):
    ffmpeg_path = os.path.join(FFMPEG_FOLDER, 'ffmpeg.exe')
    if not os.path.exists(ffmpeg_path):
        messagebox.showerror("錯誤", "找不到 ffmpeg 可執(zhí)行文件")
        return
 
    if start_time == "00:00:00.000" and end_time == "00:00:00.000":
        messagebox.showerror("錯誤", "請至少選擇一個開始時間或結(jié)束時間")
        return
 
    duration = get_video_duration(input_path)
    if duration == 0:
        return
 
    start_time_seconds = timedelta(
        hours=int(start_time.split(":")[0]),
        minutes=int(start_time.split(":")[1]),
        seconds=int(start_time.split(":")[2].split(".")[0]),
        milliseconds=int(start_time.split(":")[2].split(".")[1])
    ).total_seconds()
 
    end_time_seconds = timedelta(
        hours=int(end_time.split(":")[0]),
        minutes=int(end_time.split(":")[1]),
        seconds=int(end_time.split(":")[2].split(".")[0]),
        milliseconds=int(end_time.split(":")[2].split(".")[1])
    ).total_seconds()
 
    trim_duration = duration - start_time_seconds - end_time_seconds
    if trim_duration <= 0:
        messagebox.showerror("錯誤", "剪輯后的持續(xù)時間小于等于0")
        return
 
    cmd = [
        ffmpeg_path,
        '-ss', start_time,
        '-i', input_path,
        '-t', str(trim_duration),
        '-vcodec', 'copy',
        '-acodec', 'copy',
        output_path,
        '-y'
    ]
 
    print("執(zhí)行FFmpeg命令:", " ".join(cmd))  # 打印命令以便調(diào)試
 
    startupinfo = subprocess.STARTUPINFO()
    startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
 
    result = subprocess.run(cmd, startupinfo=startupinfo, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, encoding='utf-8')
    print("FFmpeg輸出:", result.stdout)  # 打印FFmpeg標準輸出
    print("FFmpeg錯誤:", result.stderr)  # 打印FFmpeg錯誤輸出
 
    if result.returncode != 0:
        messagebox.showerror("錯誤", f"FFmpeg執(zhí)行失敗: {result.stderr}")
 
def batch_trim_videos(input_files, output_dir, start_time, end_time):
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)
 
    for input_file in input_files:
        output_file = os.path.join(output_dir, os.path.basename(input_file))
        trim_video(input_file, output_file, start_time, end_time)
     
    with open(COMPLETION_FILE, 'w', encoding='utf-8') as f:
        f.write("老弟已經(jīng)完成了,你開心嗎")
    print("視頻剪輯完成標志已寫入文件")
 
def select_input_files():
    files = filedialog.askopenfilenames(filetypes=[("MP4 files", "*.mp4")])
    if files:
        entry_input_files.delete(0, tk.END)
        entry_input_files.insert(0, f"已選擇 {len(files)} 個文件")
        entry_input_files.files = files
 
def select_output_directory():
    directory = filedialog.askdirectory()
    if directory:
        entry_output_directory.config(state='normal')
        entry_output_directory.delete(0, tk.END)
        entry_output_directory.insert(0, directory)
        entry_output_directory.config(state='disabled', disabledbackground='#d9d9d9', disabledforeground='#000000')
        label_status.config(text="輸出目錄已選擇。請選擇開始時間和結(jié)束時間。")
        config['output_directory'] = directory
        save_config(config)
 
def validate_time_format(time_str):
    try:
        datetime.strptime(time_str, '%H:%M:%S.%f')
        return True
    except ValueError:
        return False
 
def start_trimming():
    input_files = getattr(entry_input_files, 'files', [])
    output_directory = entry_output_directory.get()
    start_time = format_time(var_start_hours.get(), var_start_minutes.get(), var_start_seconds.get(), var_start_milliseconds.get())
    end_time = format_time(var_end_hours.get(), var_end_minutes.get(), var_end_seconds.get(), var_end_milliseconds.get())
 
    # 驗證時間格式
    if not validate_time_format(start_time) or not validate_time_format(end_time):
        messagebox.showerror("錯誤", "時間格式不正確")
        return
 
    if start_time == "00:00:00.000" and end_time == "00:00:00.000":
        messagebox.showerror("錯誤", "請至少選擇一個開始時間或結(jié)束時間")
        return
 
    if not input_files:
        messagebox.showwarning("警告", "請選擇輸入文件!")
        return
    if not output_directory:
        messagebox.showwarning("警告", "請選擇輸出目錄!")
        return
 
    threading.Thread(target=batch_trim_videos, args=(input_files, output_directory, start_time, end_time)).start()
    threading.Thread(target=monitor_completion).start()
 
def monitor_completion():
    while not os.path.exists(COMPLETION_FILE):
        pass
    with open(COMPLETION_FILE, 'r', encoding='utf-8') as f:
        message = f.read()
    print("檢測到完成標志文件,內(nèi)容:", message)
    speak(message)
 
def speak(text):
    print("初始化語音引擎")
    engine = pyttsx3.init()
    print("語音引擎初始化成功")
    engine.say(text)
    print("語音引擎開始說話")
    engine.runAndWait()
    print("語音引擎說話結(jié)束")
 
def show_about():
    about_window = tk.Toplevel(root)
    about_window.title("關(guān)于")
    about_window.geometry("400x300")
    about_window.resizable(False, False)
     
    text = tk.Text(about_window, wrap='word', height=15, width=50)
    text.insert(tk.END, "n這是一個用來截取視頻片段的小工具。\n\n功能特性:\n"
                        "1. 支持批量視頻截取\n"
                        "2. 支持自定義開始時間和結(jié)束時間\n"
                        "3. 使用 FFmpeg 進行視頻處理\n"
                        "4. 提供簡單易用的圖形用戶界面\n\n"
                        "感謝使用本工具?。ㄊ菬o損快剪哈)")
    text.config(state='disabled')
     
    scrollbar = tk.Scrollbar(about_window, command=text.yview)
    text.config(yscrollcommand=scrollbar.set)
     
    text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
    scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
 
config = load_config()
 
root = tk.Tk()
root.title("視頻截取工具")
root.geometry("510x250")
root.resizable(False, False)
root.iconbitmap(ICON_PATH)  # 設置窗口圖標
 
# 創(chuàng)建菜單欄
menu_bar = tk.Menu(root)
root.config(menu=menu_bar)
 
# 創(chuàng)建菜單
menu = tk.Menu(menu_bar, tearoff=0)
menu_bar.add_cascade(label="菜單", menu=menu)
menu.add_command(label="關(guān)于", command=show_about)
 
tk.Label(root, text="選擇輸入文件:").grid(row=0, column=0, padx=5, pady=5, sticky='e')
entry_input_files = tk.Entry(root, width=50)
entry_input_files.grid(row=0, column=1, padx=5, pady=5, columnspan=4, sticky='w')
entry_input_files.files = []
tk.Button(root, text="瀏覽", command=select_input_files).grid(row=0, column=5, padx=5, pady=5, sticky='w')
 
tk.Label(root, text="選擇輸出目錄:").grid(row=1, column=0, padx=5, pady=5, sticky='e')
entry_output_directory = tk.Entry(root, width=50)
entry_output_directory.grid(row=1, column=1, padx=5, pady=5, columnspan=4, sticky='w')
tk.Button(root, text="瀏覽", command=select_output_directory).grid(row=1, column=5, padx=5, pady=5, sticky='w')
 
if 'output_directory' in config:
    entry_output_directory.insert(0, config['output_directory'])
    entry_output_directory.config(state='disabled', disabledbackground='#d9d9d9', disabledforeground='#000000')
    label_status = tk.Label(root, text="輸出目錄已選擇。請選擇開始時間和結(jié)束時間。")
else:
    label_status = tk.Label(root, text="請選擇輸出目錄。")
 
label_status.grid(row=4, column=0, columnspan=6, pady=10)
 
hours = [f"{i:02}" for i in range(24)]
minutes_seconds = [f"{i:02}" for i in range(60)]
milliseconds = [f"{i:03}" for i in range(1000)]
 
var_start_hours = tk.StringVar(value="00")
var_start_minutes = tk.StringVar(value="00")
var_start_seconds = tk.StringVar(value="00")
var_start_milliseconds = tk.StringVar(value="000")
 
var_end_hours = tk.StringVar(value="00")
var_end_minutes = tk.StringVar(value="00")
var_end_seconds = tk.StringVar(value="00")
var_end_milliseconds = tk.StringVar(value="000")
 
def create_time_frame(root, var_hours, var_minutes, var_seconds, var_milliseconds):
    frame = tk.Frame(root)
    ttk.Combobox(frame, textvariable=var_hours, values=hours, width=3).pack(side='left')
    tk.Label(frame, text="時").pack(side='left', padx=3)
    ttk.Combobox(frame, textvariable=var_minutes, values=minutes_seconds, width=3).pack(side='left')
    tk.Label(frame, text="分").pack(side='left', padx=3)
    ttk.Combobox(frame, textvariable=var_seconds, values=minutes_seconds, width=3).pack(side='left')
    tk.Label(frame, text="秒").pack(side='left', padx=3)
    ttk.Combobox(frame, textvariable=var_milliseconds, values=milliseconds, width=4).pack(side='left')
    tk.Label(frame, text="毫秒").pack(side='left', padx=3)
    return frame
 
tk.Label(root, text="開始時間:").grid(row=2, column=0, padx=5, pady=5, sticky='e')
start_time_frame = create_time_frame(root, var_start_hours, var_start_minutes, var_start_seconds, var_start_milliseconds)
start_time_frame.grid(row=2, column=1, columnspan=5, padx=5, pady=5, sticky='w')
 
tk.Label(root, text="結(jié)束時間:").grid(row=3, column=0, padx=5, pady=5, sticky='e')
end_time_frame = create_time_frame(root, var_end_hours, var_end_minutes, var_end_seconds, var_end_milliseconds)
end_time_frame.grid(row=3, column=1, columnspan=5, padx=5, pady=5, sticky='w')
 
tk.Button(root, text="開始截取", command=start_trimming).grid(row=5, column=0, columnspan=6, pady=10, sticky='ew')
 
root.mainloop()

到此這篇關(guān)于Python進行批量剪輯視頻片頭片尾的文章就介紹到這了,更多相關(guān)Python剪輯視頻內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳析Python面向?qū)ο笾械睦^承

    詳析Python面向?qū)ο笾械睦^承

    這篇文章主要詳析Python面向?qū)ο笾械睦^承,類繼承作為python的三大特性之一,在我們學習python的時候是必不可少的。使用類繼承,能夠大大減少重復代碼的編寫,下文詳細內(nèi)容需要的小伙伴可以參考一下
    2022-03-03
  • Python?NLTK庫全面解析及代碼示例(NLP核心庫)

    Python?NLTK庫全面解析及代碼示例(NLP核心庫)

    NLTK是Python中用于自然語言處理(NLP)的核心庫,提供了豐富的文本處理工具、算法和語料庫,下面通過實例代碼場景分析給大家詳細介紹Python?NLTK庫全面解析,感興趣的朋友一起看看吧
    2025-06-06
  • LyScript實現(xiàn)Hook隱藏調(diào)試器的方法詳解

    LyScript實現(xiàn)Hook隱藏調(diào)試器的方法詳解

    LyScript?插件集成的內(nèi)置API函數(shù)可靈活的實現(xiàn)繞過各類反調(diào)試保護機制。本文將運用LyScript實現(xiàn)繞過大多數(shù)通用調(diào)試機制,實現(xiàn)隱藏調(diào)試器的目的,需要的可以參考一下
    2022-09-09
  • 如何使用Python創(chuàng)建json文件

    如何使用Python創(chuàng)建json文件

    眾所周知JSON(JavaScript Object Notation)是一種輕量級的數(shù)據(jù)交換格式,這篇文章主要給大家介紹了關(guān)于如何使用Python創(chuàng)建json文件的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2023-06-06
  • python通過colorama模塊在控制臺輸出彩色文字的方法

    python通過colorama模塊在控制臺輸出彩色文字的方法

    這篇文章主要介紹了python通過colorama模塊在控制臺輸出彩色文字的方法,實例分析了colorama模塊的功能及相關(guān)使用技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-03-03
  • python3中關(guān)于excel追加寫入格式被覆蓋問題(實例代碼)

    python3中關(guān)于excel追加寫入格式被覆蓋問題(實例代碼)

    這篇文章主要介紹了python3中關(guān)于excel追加寫入格式被覆蓋問題,本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-01-01
  • python數(shù)據(jù)處理 根據(jù)顏色對圖片進行分類的方法

    python數(shù)據(jù)處理 根據(jù)顏色對圖片進行分類的方法

    今天小編就為大家分享一篇python數(shù)據(jù)處理 根據(jù)顏色對圖片進行分類的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-12-12
  • Python3中的2to3轉(zhuǎn)換工具使用示例

    Python3中的2to3轉(zhuǎn)換工具使用示例

    這篇文章主要介紹了Python3中的2to3轉(zhuǎn)換工具使用示例,本文詳細講解了使用的步驟,并總結(jié)了一些使用注意事項,需要的朋友可以參考下
    2015-06-06
  • Python中實現(xiàn)WebSocket的示例詳解

    Python中實現(xiàn)WebSocket的示例詳解

    WebSocket 是一種計算機通信協(xié)議,它為客戶端和服務器之間的雙向通信提供了一個全雙工的通道,本篇文章將詳解 Python 中如何實現(xiàn) WebSocket,感興趣的可以了解下
    2025-03-03
  • Python學習之路安裝pycharm的教程詳解

    Python學習之路安裝pycharm的教程詳解

    pycharm 是一款功能強大的 Python 編輯器,具有跨平臺性。這篇文章主要介紹了Python學習之路安裝pycharm的教程,本文分步驟通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-06-06

最新評論

乐业县| 报价| 都匀市| 修武县| 察雅县| 瓦房店市| 浦北县| 巴南区| 南投市| 乌苏市| 盐城市| 溧水县| 阳谷县| 祁东县| 宜章县| 宝丰县| 兰考县| 南宫市| 沁阳市| 土默特左旗| 普陀区| 马鞍山市| 子长县| 神木县| 沙坪坝区| 米易县| 昭苏县| 云浮市| 微山县| 庆元县| 陇西县| 万载县| 丰宁| 康定县| 登封市| 成安县| 邵武市| 海南省| 阳城县| 清涧县| 青冈县|