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

如何使用 Python和 FFmpeg 批量截圖視頻到各自文件夾中

 更新時(shí)間:2024年08月26日 10:00:59   作者:winfredzhang  
wxPython 提供了一個(gè)簡(jiǎn)單易用的界面,而 FFmpeg 則負(fù)責(zé)處理視頻幀的提取,這個(gè)工具不僅對(duì)視頻編輯工作有幫助,也為批量處理視頻文件提供了極大的便利,這篇文章主要介紹了使用 Python和 FFmpeg 批量截圖視頻到各自文件夾中,需要的朋友可以參考下

在這篇博客中,我們將創(chuàng)建一個(gè)簡(jiǎn)單的圖形用戶界面 (GUI) 工具,利用 wxPythonFFmpeg 來從視頻文件中批量生成截圖。這個(gè)工具能夠讓用戶選擇一個(gè)文件夾,遍歷其中的所有視頻文件,按照視頻長(zhǎng)度將其分為四等分,然后為每個(gè)視頻生成四張截圖。所有生成的截圖將保存在一個(gè)以視頻名稱命名的文件夾中,并在截圖完成后自動(dòng)打開該文件夾。
C:\pythoncode\new\multivideofilescreenshot.py

工具介紹

  • wxPython:用于創(chuàng)建桌面應(yīng)用程序的圖形界面。
  • FFmpeg:一個(gè)強(qiáng)大的多媒體處理工具,用于提取視頻幀。

所有代碼

import wx
import os
import subprocess
import threading
import datetime
import sys
class VideoScreenshotApp(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, title="視頻截圖工具", size=(600, 400))
        # 創(chuàng)建面板
        panel = wx.Panel(self)
        # 創(chuàng)建路徑選擇控件
        self.path_label = wx.StaticText(panel, label="請(qǐng)選擇文件夾:")
        self.path_textctrl = wx.TextCtrl(panel, style=wx.TE_READONLY)
        self.path_button = wx.Button(panel, label="選擇路徑")
        self.path_button.Bind(wx.EVT_BUTTON, self.on_select_path)
        # 創(chuàng)建文件列表控件,使用 CheckListBox 以支持多選
        self.file_list_ctrl = wx.CheckListBox(panel)
        # 創(chuàng)建截圖按鈕
        self.capture_button = wx.Button(panel, label="截圖")
        self.capture_button.Bind(wx.EVT_BUTTON, self.on_capture)
        # 布局
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.path_label, 0, wx.ALL, 5)
        sizer.Add(self.path_textctrl, 0, wx.EXPAND | wx.ALL, 5)
        sizer.Add(self.path_button, 0, wx.ALL, 5)
        sizer.Add(self.file_list_ctrl, 1, wx.EXPAND | wx.ALL, 5)
        sizer.Add(self.capture_button, 0, wx.ALL | wx.ALIGN_CENTER, 5)
        panel.SetSizer(sizer)
        self.current_path = ""
    def on_select_path(self, event):
        dlg = wx.DirDialog(self, "選擇文件夾", style=wx.DD_DEFAULT_STYLE)
        if dlg.ShowModal() == wx.ID_OK:
            self.current_path = dlg.GetPath()
            self.path_textctrl.SetValue(self.current_path)
            self.update_file_list()
        dlg.Destroy()
    def update_file_list(self):
        self.file_list_ctrl.Clear()
        if not self.current_path:
            return
        file_list = self.search_video_files(self.current_path)
        for filename, file_path, duration in file_list:
            self.file_list_ctrl.Append(f"{filename} - {str(datetime.timedelta(seconds=int(duration)))}", file_path)
    def search_video_files(self, directory):
        video_extensions = ['.mp4', '.avi', '.mkv', '.mov', '.wmv', '.flv', '.webm']
        file_list = []
        for root, dirs, files in os.walk(directory):
            for file in files:
                if os.path.splitext(file)[1].lower() in video_extensions:
                    file_path = os.path.join(root, file)
                    duration = self.get_video_duration(file_path)
                    file_list.append((file, file_path, duration))
        return file_list
    def get_video_duration(self, file_path):
        cmd = [
            'ffprobe',
            '-v', 'error',
            '-select_streams', 'v:0',
            '-show_entries', 'stream=duration',
            '-of', 'default=noprint_wrappers=1:nokey=1',
            file_path
        ]
        try:
            result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=True)
            duration_str = result.stdout.strip()
            if not duration_str:
                raise ValueError("ffprobe output is empty")
            return float(duration_str)
        except subprocess.CalledProcessError as e:
            wx.LogError(f"ffprobe error: {e.stderr}")
            raise
        except ValueError as e:
            wx.LogError(f"Value error: {e}")
            raise
    def on_capture(self, event):
        selected_indices = self.file_list_ctrl.GetCheckedItems()
        if selected_indices:
            for index in selected_indices:
                file_path = self.file_list_ctrl.GetClientData(index)
                file_name = os.path.basename(file_path)
                duration = self.get_video_duration(file_path)
                thread = threading.Thread(target=self.capture_screenshots, args=(file_path, duration))
                thread.start()
        else:
            wx.MessageBox("請(qǐng)先選擇一個(gè)或多個(gè)視頻文件", "提示", wx.OK | wx.ICON_INFORMATION)
    def capture_screenshots(self, file_path, duration):
        output_dir = os.path.join(self.current_path, os.path.splitext(os.path.basename(file_path))[0])
        if not os.path.exists(output_dir):
            os.makedirs(output_dir)
        # 計(jì)算每張截圖的時(shí)間點(diǎn)
        intervals = [duration * i / 4 for i in range(1, 5)]
        # 生成截圖
        for i, timestamp in enumerate(intervals):
            cmd = [
                'ffmpeg',
                '-ss', str(datetime.timedelta(seconds=int(timestamp))),
                '-i', file_path,
                '-vframes', '1',
                os.path.join(output_dir, f'screenshot_{i+1}.jpg')
            ]
            subprocess.run(cmd, check=True)
        # 截圖完成后,自動(dòng)打開文件夾
        if sys.platform.startswith('win'):
            subprocess.Popen(['explorer', output_dir])
        elif sys.platform.startswith('darwin'):
            subprocess.Popen(['open', output_dir])
        elif sys.platform.startswith('linux'):
            subprocess.Popen(['xdg-open', output_dir])
if __name__ == "__main__":
    app = wx.App(False)
    frame = VideoScreenshotApp()
    frame.Show()
    app.MainLoop()

代碼實(shí)現(xiàn)

下面是我們的工具實(shí)現(xiàn)代碼:

import wx
import os
import subprocess
import threading
import datetime
import sys
class VideoScreenshotApp(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, title="視頻截圖工具", size=(600, 400))
        # 創(chuàng)建面板
        panel = wx.Panel(self)
        # 創(chuàng)建路徑選擇控件
        self.path_label = wx.StaticText(panel, label="請(qǐng)選擇文件夾:")
        self.path_textctrl = wx.TextCtrl(panel, style=wx.TE_READONLY)
        self.path_button = wx.Button(panel, label="選擇路徑")
        self.path_button.Bind(wx.EVT_BUTTON, self.on_select_path)
        # 創(chuàng)建文件列表控件,使用 CheckListBox 以支持多選
        self.file_list_ctrl = wx.CheckListBox(panel)
        # 創(chuàng)建截圖按鈕
        self.capture_button = wx.Button(panel, label="截圖")
        self.capture_button.Bind(wx.EVT_BUTTON, self.on_capture)
        # 布局
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.path_label, 0, wx.ALL, 5)
        sizer.Add(self.path_textctrl, 0, wx.EXPAND | wx.ALL, 5)
        sizer.Add(self.path_button, 0, wx.ALL, 5)
        sizer.Add(self.file_list_ctrl, 1, wx.EXPAND | wx.ALL, 5)
        sizer.Add(self.capture_button, 0, wx.ALL | wx.ALIGN_CENTER, 5)
        panel.SetSizer(sizer)
        self.current_path = ""
    def on_select_path(self, event):
        dlg = wx.DirDialog(self, "選擇文件夾", style=wx.DD_DEFAULT_STYLE)
        if dlg.ShowModal() == wx.ID_OK:
            self.current_path = dlg.GetPath()
            self.path_textctrl.SetValue(self.current_path)
            self.update_file_list()
        dlg.Destroy()
    def update_file_list(self):
        self.file_list_ctrl.Clear()
        if not self.current_path:
            return
        file_list = self.search_video_files(self.current_path)
        for filename, file_path, duration in file_list:
            self.file_list_ctrl.Append(f"{filename} - {str(datetime.timedelta(seconds=int(duration)))}", file_path)
    def search_video_files(self, directory):
        video_extensions = ['.mp4', '.avi', '.mkv', '.mov', '.wmv', '.flv', '.webm']
        file_list = []
        for root, dirs, files in os.walk(directory):
            for file in files:
                if os.path.splitext(file)[1].lower() in video_extensions:
                    file_path = os.path.join(root, file)
                    duration = self.get_video_duration(file_path)
                    file_list.append((file, file_path, duration))
        return file_list
    def get_video_duration(self, file_path):
        cmd = [
            'ffprobe',
            '-v', 'error',
            '-select_streams', 'v:0',
            '-show_entries', 'stream=duration',
            '-of', 'default=noprint_wrappers=1:nokey=1',
            file_path
        ]
        try:
            result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=True)
            duration_str = result.stdout.strip()
            if not duration_str:
                raise ValueError("ffprobe output is empty")
            return float(duration_str)
        except subprocess.CalledProcessError as e:
            wx.LogError(f"ffprobe error: {e.stderr}")
            raise
        except ValueError as e:
            wx.LogError(f"Value error: {e}")
            raise
    def on_capture(self, event):
        selected_indices = self.file_list_ctrl.GetCheckedItems()
        if selected_indices:
            for index in selected_indices:
                file_path = self.file_list_ctrl.GetClientData(index)
                file_name = os.path.basename(file_path)
                duration = self.get_video_duration(file_path)
                thread = threading.Thread(target=self.capture_screenshots, args=(file_path, duration))
                thread.start()
        else:
            wx.MessageBox("請(qǐng)先選擇一個(gè)或多個(gè)視頻文件", "提示", wx.OK | wx.ICON_INFORMATION)
    def capture_screenshots(self, file_path, duration):
        output_dir = os.path.join(self.current_path, os.path.splitext(os.path.basename(file_path))[0])
        if not os.path.exists(output_dir):
            os.makedirs(output_dir)
        # 計(jì)算每張截圖的時(shí)間點(diǎn)
        intervals = [duration * i / 4 for i in range(1, 5)]
        # 生成截圖
        for i, timestamp in enumerate(intervals):
            cmd = [
                'ffmpeg',
                '-ss', str(datetime.timedelta(seconds=int(timestamp))),
                '-i', file_path,
                '-vframes', '1',
                os.path.join(output_dir, f'screenshot_{i+1}.jpg')
            ]
            subprocess.run(cmd, check=True)
        # 截圖完成后,自動(dòng)打開文件夾
        if sys.platform.startswith('win'):
            subprocess.Popen(['explorer', output_dir])
        elif sys.platform.startswith('darwin'):
            subprocess.Popen(['open', output_dir])
        elif sys.platform.startswith('linux'):
            subprocess.Popen(['xdg-open', output_dir])
if __name__ == "__main__":
    app = wx.App(False)
    frame = VideoScreenshotApp()
    frame.Show()
    app.MainLoop()

代碼解釋

創(chuàng)建主窗口

  • 使用 wx.Frame 創(chuàng)建主窗口,添加路徑選擇控件、文件列表控件以及截圖按鈕。

路徑選擇

  • on_select_path 方法允許用戶選擇一個(gè)文件夾,并更新文件列表。

文件列表更新

  • update_file_list 方法遍歷所選文件夾中的視頻文件,獲取每個(gè)視頻的時(shí)長(zhǎng),并將信息顯示在 CheckListBox 中。

視頻時(shí)長(zhǎng)獲取

  • get_video_duration 方法使用 ffprobe 命令來獲取視頻時(shí)長(zhǎng)。

截圖生成

  • on_capture 方法處理截圖請(qǐng)求,使用多線程來生成截圖,以避免阻塞主線程。
  • capture_screenshots 方法使用 ffmpeg 命令生成四張截圖,并將截圖保存在以視頻名稱命名的文件夾中。

自動(dòng)打開文件夾

  • 截圖完成后,自動(dòng)在文件瀏覽器中打開保存截圖的文件夾。

效果如下

在這里插入圖片描述

總結(jié)

通過這個(gè)工具,你可以輕松地從多個(gè)視頻文件中生成截圖,而無需手動(dòng)操作。wxPython 提供了一個(gè)簡(jiǎn)單易用的界面,而 FFmpeg 則負(fù)責(zé)處理視頻幀的提取。這個(gè)工具不僅對(duì)視頻編輯工作有幫助,也為批量處理視頻文件提供了極大的便利。

以上就是使用 Python和 FFmpeg 批量截圖視頻到各自文件夾中的詳細(xì)內(nèi)容,更多關(guān)于Python FFmpeg 批量截圖視頻的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • APPium+Python編寫真機(jī)移動(dòng)端自動(dòng)化腳本的項(xiàng)目實(shí)踐

    APPium+Python編寫真機(jī)移動(dòng)端自動(dòng)化腳本的項(xiàng)目實(shí)踐

    本文主要介紹了APPium+Python編寫真機(jī)移動(dòng)端自動(dòng)化腳本的項(xiàng)目實(shí)踐,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • Python光學(xué)仿真wxpython透鏡演示系統(tǒng)初始化與參數(shù)調(diào)節(jié)

    Python光學(xué)仿真wxpython透鏡演示系統(tǒng)初始化與參數(shù)調(diào)節(jié)

    這篇文章主要為大家介紹了Python光學(xué)仿真wxpython透鏡演示系統(tǒng)的初始化與參數(shù)調(diào)節(jié),同樣在學(xué)習(xí)wxpython透鏡演示系統(tǒng)的入門同學(xué)可以借鑒參考下,希望能夠有所幫助
    2021-10-10
  • 使用pyproject.toml構(gòu)建現(xiàn)代化Python項(xiàng)目的詳細(xì)步驟

    使用pyproject.toml構(gòu)建現(xiàn)代化Python項(xiàng)目的詳細(xì)步驟

    如果你曾經(jīng)接觸過 Python 項(xiàng)目,可能對(duì) setup.py、setup.cfg、requirements.txt 這些文件并不陌生,但隨著 Python 生態(tài)的發(fā)展,這種分散的配置方式逐漸暴露出諸多問題,pyproject.toml 的出現(xiàn)正是為了解決這些痛點(diǎn),本文詳細(xì)講解如何從零開始配置 pyproject.toml
    2026-05-05
  • Python繪制指數(shù)概率分布函數(shù)

    Python繪制指數(shù)概率分布函數(shù)

    指數(shù)分布是一種廣泛應(yīng)用于數(shù)據(jù)科學(xué)和統(tǒng)計(jì)學(xué)中的連續(xù)概率分布,本文將詳細(xì)介紹如何在Python中快速上手繪制指數(shù)分布的概率密度函數(shù)圖,需要的可以參考下
    2025-01-01
  • 利用python獲取某年中每個(gè)月的第一天和最后一天

    利用python獲取某年中每個(gè)月的第一天和最后一天

    最近在做項(xiàng)目的時(shí)候,突然想到的這個(gè)問題,覺得比較有趣,就實(shí)際測(cè)試了一下,考慮到以后可能會(huì)有用,就總結(jié)下來寫了這篇文章,剛興趣的朋友們可以參考學(xué)習(xí)下,下面來跟著小編一起看看吧。
    2016-12-12
  • 如何Python使用設(shè)置word的頁邊距

    如何Python使用設(shè)置word的頁邊距

    在編寫或處理Word文檔的過程中,頁邊距是一個(gè)不可忽視的排版要素,本文將介紹如何使用Python設(shè)置Word文檔中各個(gè)節(jié)的頁邊距,需要的可以參考下
    2025-05-05
  • 詳解Python+Pyecharts實(shí)現(xiàn)漏斗圖的繪制

    詳解Python+Pyecharts實(shí)現(xiàn)漏斗圖的繪制

    漏斗圖是一個(gè)簡(jiǎn)單的散點(diǎn)圖,反映研究在一定樣本量或精確性下單個(gè)研究的干預(yù)效應(yīng)估計(jì)值。本文將用Python Pyecharts實(shí)現(xiàn)漏斗圖的繪制,需要的可以參考一下
    2022-06-06
  • 在python里創(chuàng)建一個(gè)任務(wù)(Task)實(shí)例

    在python里創(chuàng)建一個(gè)任務(wù)(Task)實(shí)例

    這篇文章主要介紹了在python里創(chuàng)建一個(gè)任務(wù)(Task)實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-04-04
  • Python雙鏈表原理與實(shí)現(xiàn)方法詳解

    Python雙鏈表原理與實(shí)現(xiàn)方法詳解

    這篇文章主要介紹了Python雙鏈表原理與實(shí)現(xiàn)方法,結(jié)合實(shí)例形式詳細(xì)分析了Python雙鏈表的概念、原理、用法及相關(guān)操作注意事項(xiàng),需要的朋友可以參考下
    2020-02-02
  • Django使用echarts進(jìn)行可視化展示的實(shí)踐

    Django使用echarts進(jìn)行可視化展示的實(shí)踐

    可視化是將數(shù)據(jù)轉(zhuǎn)換成圖形或圖像在屏幕上顯示出來,本文主要介紹了Django使用echarts進(jìn)行可視化展示的實(shí)踐,感興趣的可以了解一下
    2021-06-06

最新評(píng)論

望城县| 三穗县| 虞城县| 桃源县| 来宾市| 韶山市| 阿城市| 萝北县| 百色市| 临沂市| 临猗县| 龙州县| 安新县| 玛多县| 静乐县| 新昌县| 黄浦区| 重庆市| 康平县| 吉隆县| 阜城县| 娄底市| 南涧| 苏尼特右旗| 卓资县| 朝阳市| 大石桥市| 永新县| 永德县| 苗栗县| 三明市| 荆州市| 乐陵市| 包头市| 屯留县| 峨边| 鲜城| 永平县| 通许县| 湘乡市| 英吉沙县|