Python+moviepy實(shí)現(xiàn)音頻/視頻提取器
在這篇博客中,我們將深入探討一個(gè)使用Python和wxPython構(gòu)建的音頻/視頻提取器應(yīng)用程序。這個(gè)應(yīng)用程序允許用戶從視頻文件中提取音頻,或者從音頻文件中截取特定時(shí)間段。讓我們逐步分析這個(gè)程序的功能和實(shí)現(xiàn)。
C:\pythoncode\new\MP3towav.py
全部代碼
import wx
import os
import subprocess
from datetime import datetime
import json
from moviepy.editor import VideoFileClip, AudioFileClip
class AudioVideoExtractor(wx.Frame):
def __init__(self):
super().__init__(parent=None, title='Audio/Video Extractor')
self.panel = wx.Panel(self)
self.create_widgets()
self.load_settings()
def create_widgets(self):
# File selection
self.file_picker = wx.FilePickerCtrl(self.panel, message="Choose an audio or video file")
# Time range
self.start_time = wx.TextCtrl(self.panel, value="00:00:00")
self.end_time = wx.TextCtrl(self.panel, value="00:00:00")
# Output format
self.formats = ['mp3', 'wav', 'aac']
self.format_choice = wx.Choice(self.panel, choices=self.formats)
# Output directory
self.dir_picker = wx.DirPickerCtrl(self.panel, message="Choose output directory")
# Export button
self.export_btn = wx.Button(self.panel, label="Export")
self.export_btn.Bind(wx.EVT_BUTTON, self.on_export)
# Open button
self.open_btn = wx.Button(self.panel, label="Open in PotPlayer")
self.open_btn.Bind(wx.EVT_BUTTON, self.on_open)
# Layout
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(wx.StaticText(self.panel, label="Select Audio or Video File:"), 0, wx.ALL, 5)
sizer.Add(self.file_picker, 0, wx.EXPAND|wx.ALL, 5)
sizer.Add(wx.StaticText(self.panel, label="Start Time (HH:MM:SS):"), 0, wx.ALL, 5)
sizer.Add(self.start_time, 0, wx.EXPAND|wx.ALL, 5)
sizer.Add(wx.StaticText(self.panel, label="End Time (HH:MM:SS):"), 0, wx.ALL, 5)
sizer.Add(self.end_time, 0, wx.EXPAND|wx.ALL, 5)
sizer.Add(wx.StaticText(self.panel, label="Output Format:"), 0, wx.ALL, 5)
sizer.Add(self.format_choice, 0, wx.EXPAND|wx.ALL, 5)
sizer.Add(wx.StaticText(self.panel, label="Output Directory:"), 0, wx.ALL, 5)
sizer.Add(self.dir_picker, 0, wx.EXPAND|wx.ALL, 5)
sizer.Add(self.export_btn, 0, wx.ALL|wx.CENTER, 5)
sizer.Add(self.open_btn, 0, wx.ALL|wx.CENTER, 5)
self.panel.SetSizer(sizer)
def on_export(self, event):
input_path = self.file_picker.GetPath()
start_time = self.start_time.GetValue()
end_time = self.end_time.GetValue()
output_format = self.formats[self.format_choice.GetSelection()]
output_dir = self.dir_picker.GetPath()
if not all([input_path, start_time, end_time, output_format, output_dir]):
wx.MessageBox("Please fill in all fields", "Error", wx.OK | wx.ICON_ERROR)
return
try:
# Check if the input file is video or audio
file_extension = os.path.splitext(input_path)[1].lower()
if file_extension in ['.mp4', '.avi', '.mov', '.flv']: # Add more video extensions if needed
clip = VideoFileClip(input_path).audio
elif file_extension in ['.mp3', '.wav', '.aac', '.flac']: # Add more audio extensions if needed
clip = AudioFileClip(input_path)
else:
raise ValueError("Unsupported file format")
start = self.time_to_seconds(start_time)
end = self.time_to_seconds(end_time)
clip = clip.subclip(start, end)
timestamp = datetime.now().strftime("%Y%m%d")
counter = 1
while True:
output_filename = f"{timestamp}_{counter:03d}.{output_format}"
output_path = os.path.join(output_dir, output_filename)
if not os.path.exists(output_path):
break
counter += 1
clip.write_audiofile(output_path)
clip.close()
self.last_exported_file = output_path
wx.MessageBox(f"Audio exported to {output_path}", "Success", wx.OK | wx.ICON_INFORMATION)
self.save_settings()
except Exception as e:
wx.MessageBox(f"Error: {str(e)}", "Error", wx.OK | wx.ICON_ERROR)
def on_open(self, event):
if hasattr(self, 'last_exported_file') and os.path.exists(self.last_exported_file):
try:
subprocess.Popen(['C:\\Program Files\\DAUM\\PotPlayer\\PotPlayerMini64.exe', self.last_exported_file])
except Exception as e:
wx.MessageBox(f"Error opening file: {str(e)}", "Error", wx.OK | wx.ICON_ERROR)
else:
wx.MessageBox("No file has been exported yet", "Error", wx.OK | wx.ICON_ERROR)
def time_to_seconds(self, time_str):
h, m, s = map(int, time_str.split(':'))
return h * 3600 + m * 60 + s
def save_settings(self):
settings = {
'last_file': self.file_picker.GetPath(),
'start_time': self.start_time.GetValue(),
'end_time': self.end_time.GetValue(),
'format': self.format_choice.GetSelection(),
'output_dir': self.dir_picker.GetPath()
}
with open('settings.json', 'w') as f:
json.dump(settings, f)
def load_settings(self):
if os.path.exists('settings.json'):
with open('settings.json', 'r') as f:
settings = json.load(f)
self.file_picker.SetPath(settings.get('last_file', ''))
self.start_time.SetValue(settings.get('start_time', '00:00:00'))
self.end_time.SetValue(settings.get('end_time', '00:00:00'))
self.format_choice.SetSelection(settings.get('format', 0))
self.dir_picker.SetPath(settings.get('output_dir', ''))
if __name__ == '__main__':
app = wx.App()
frame = AudioVideoExtractor()
frame.Show()
app.MainLoop()
1. 概述
這個(gè)應(yīng)用程序的主要功能包括:
- 從視頻文件中提取音頻
- 從音頻文件中截取特定時(shí)間段
- 設(shè)置輸出音頻格式
- 自定義輸出文件名和路徑
- 使用PotPlayer播放導(dǎo)出的音頻文件
- 保存和加載用戶設(shè)置
2. 導(dǎo)入必要的庫(kù)
import wx import os import subprocess from datetime import datetime import json from moviepy.editor import VideoFileClip, AudioFileClip
這些庫(kù)為我們提供了以下功能:
- wx: 用于創(chuàng)建圖形用戶界面
- os: 用于文件和路徑操作
- subprocess: 用于啟動(dòng)外部程序(PotPlayer)
- datetime: 用于生成時(shí)間戳
- json: 用于保存和加載設(shè)置
- moviepy.editor: 用于處理音頻和視頻文件
3. 主應(yīng)用程序類(lèi)
class AudioVideoExtractor(wx.Frame):
def __init__(self):
super().__init__(parent=None, title='Audio/Video Extractor')
self.panel = wx.Panel(self)
self.create_widgets()
self.load_settings()
這個(gè)類(lèi)繼承自wx.Frame,是我們應(yīng)用程序的主窗口。在初始化方法中,我們創(chuàng)建了一個(gè)面板,調(diào)用方法來(lái)創(chuàng)建UI組件,并加載之前保存的設(shè)置。
4. 創(chuàng)建UI組件
def create_widgets(self):
# 文件選擇器
self.file_picker = wx.FilePickerCtrl(self.panel, message="Choose an audio or video file")
# 時(shí)間范圍輸入
self.start_time = wx.TextCtrl(self.panel, value="00:00:00")
self.end_time = wx.TextCtrl(self.panel, value="00:00:00")
# 輸出格式選擇
self.formats = ['mp3', 'wav', 'aac']
self.format_choice = wx.Choice(self.panel, choices=self.formats)
# 輸出目錄選擇
self.dir_picker = wx.DirPickerCtrl(self.panel, message="Choose output directory")
# 導(dǎo)出按鈕
self.export_btn = wx.Button(self.panel, label="Export")
self.export_btn.Bind(wx.EVT_BUTTON, self.on_export)
# 打開(kāi)按鈕
self.open_btn = wx.Button(self.panel, label="Open in PotPlayer")
self.open_btn.Bind(wx.EVT_BUTTON, self.on_open)
# 布局設(shè)置
# ...這個(gè)方法創(chuàng)建了所有的UI組件,包括文件選擇器、時(shí)間輸入框、格式選擇下拉框、目錄選擇器和按鈕。它還設(shè)置了組件的布局。
5. 導(dǎo)出功能
def on_export(self, event):
# 獲取用戶輸入
input_path = self.file_picker.GetPath()
start_time = self.start_time.GetValue()
end_time = self.end_time.GetValue()
output_format = self.formats[self.format_choice.GetSelection()]
output_dir = self.dir_picker.GetPath()
# 檢查輸入是否完整
if not all([input_path, start_time, end_time, output_format, output_dir]):
wx.MessageBox("Please fill in all fields", "Error", wx.OK | wx.ICON_ERROR)
return
try:
# 檢查輸入文件類(lèi)型
file_extension = os.path.splitext(input_path)[1].lower()
if file_extension in ['.mp4', '.avi', '.mov', '.flv']:
clip = VideoFileClip(input_path).audio
elif file_extension in ['.mp3', '.wav', '.aac', '.flac']:
clip = AudioFileClip(input_path)
else:
raise ValueError("Unsupported file format")
# 處理音頻
start = self.time_to_seconds(start_time)
end = self.time_to_seconds(end_time)
clip = clip.subclip(start, end)
# 生成輸出文件名
timestamp = datetime.now().strftime("%Y%m%d")
counter = 1
while True:
output_filename = f"{timestamp}_{counter:03d}.{output_format}"
output_path = os.path.join(output_dir, output_filename)
if not os.path.exists(output_path):
break
counter += 1
# 導(dǎo)出音頻
clip.write_audiofile(output_path)
clip.close()
self.last_exported_file = output_path
wx.MessageBox(f"Audio exported to {output_path}", "Success", wx.OK | wx.ICON_INFORMATION)
self.save_settings()
except Exception as e:
wx.MessageBox(f"Error: {str(e)}", "Error", wx.OK | wx.ICON_ERROR)這個(gè)方法是程序的核心,它處理音頻/視頻的導(dǎo)出過(guò)程:
- 獲取用戶輸入的所有必要信息。
- 檢查輸入文件的類(lèi)型(音頻或視頻)。
- 根據(jù)用戶指定的時(shí)間范圍截取音頻。
- 生成一個(gè)唯一的輸出文件名。
- 導(dǎo)出音頻文件。
- 保存用戶設(shè)置以便下次使用。
6. 在PotPlayer中打開(kāi)文件
def on_open(self, event):
if hasattr(self, 'last_exported_file') and os.path.exists(self.last_exported_file):
try:
subprocess.Popen(['potplayer.exe', self.last_exported_file])
except Exception as e:
wx.MessageBox(f"Error opening file: {str(e)}", "Error", wx.OK | wx.ICON_ERROR)
else:
wx.MessageBox("No file has been exported yet", "Error", wx.OK | wx.ICON_ERROR)
這個(gè)方法允許用戶直接在PotPlayer中打開(kāi)最近導(dǎo)出的文件。
7. 設(shè)置的保存和加載
def save_settings(self):
settings = {
'last_file': self.file_picker.GetPath(),
'start_time': self.start_time.GetValue(),
'end_time': self.end_time.GetValue(),
'format': self.format_choice.GetSelection(),
'output_dir': self.dir_picker.GetPath()
}
with open('settings.json', 'w') as f:
json.dump(settings, f)
???????def load_settings(self):
if os.path.exists('settings.json'):
with open('settings.json', 'r') as f:
settings = json.load(f)
self.file_picker.SetPath(settings.get('last_file', ''))
self.start_time.SetValue(settings.get('start_time', '00:00:00'))
self.end_time.SetValue(settings.get('end_time', '00:00:00'))
self.format_choice.SetSelection(settings.get('format', 0))
self.dir_picker.SetPath(settings.get('output_dir', ''))這些方法允許程序保存用戶的設(shè)置并在下次啟動(dòng)時(shí)加載它們,提高了用戶體驗(yàn)。
8. 主程序入口
if __name__ == '__main__':
app = wx.App()
frame = AudioVideoExtractor()
frame.Show()
app.MainLoop()
這是程序的入口點(diǎn),它創(chuàng)建了wxPython應(yīng)用程序?qū)嵗?實(shí)例化了我們的AudioVideoExtractor類(lèi),并啟動(dòng)主事件循環(huán)。
9.運(yùn)行結(jié)果

結(jié)論
這個(gè)音頻/視頻提取器是一個(gè)功能強(qiáng)大yet易用的工具,展示了如何使用Python和wxPython創(chuàng)建實(shí)用的桌面應(yīng)用程序。它結(jié)合了文件I/O、音頻/視頻處理、GUI編程和設(shè)置管理等多個(gè)方面,是一個(gè)很好的學(xué)習(xí)案例。
以上就是Python+moviepy實(shí)現(xiàn)音頻/視頻提取器的詳細(xì)內(nèi)容,更多關(guān)于Python音頻視頻提取器的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python如何讀寫(xiě)JSON格式數(shù)據(jù)
這篇文章主要介紹了Python如何讀寫(xiě)JSON格式數(shù)據(jù),JSON文件的讀寫(xiě)應(yīng)算成Python基礎(chǔ)知識(shí)的內(nèi)容,在編寫(xiě)Nonebot插件時(shí),常常會(huì)操作JSON類(lèi)型的數(shù)據(jù),需要的朋友可以參考下2023-04-04
Object arrays cannot be loaded when
這篇文章主要介紹了Object arrays cannot be loaded when allow_pickle=False,本文給大家分享問(wèn)題解決思路,需要的朋友可以參考下2022-11-11
深入剖析Python的爬蟲(chóng)框架Scrapy的結(jié)構(gòu)與運(yùn)作流程
這篇文章主要介紹了Python的爬蟲(chóng)框架Scrapy的結(jié)構(gòu)與運(yùn)作流程,并以一個(gè)實(shí)際的項(xiàng)目來(lái)講解Scrapy的原理機(jī)制,十分推薦!需要的朋友可以參考下2016-01-01
解決Jupyter NoteBook輸出的圖表太小看不清問(wèn)題
這篇文章主要介紹了解決Jupyter NoteBook輸出的圖表太小看不清問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-04-04
NumPy 數(shù)學(xué)函數(shù)及代數(shù)運(yùn)算的實(shí)現(xiàn)代碼
這篇文章主要介紹了NumPy 數(shù)學(xué)函數(shù)及代數(shù)運(yùn)算的實(shí)現(xiàn)代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-07-07
學(xué)習(xí)Python,你還不知道m(xù)ain函數(shù)嗎
Python?中的?main?函數(shù)充當(dāng)程序的執(zhí)行點(diǎn),在?Python?編程中定義?main?函數(shù)是啟動(dòng)程序執(zhí)行的必要條件。本文就來(lái)帶大家深入了解一下main函數(shù),感興趣的可以了解一下2022-09-09
python爬蟲(chóng)之urllib,偽裝,超時(shí)設(shè)置,異常處理的方法
今天小編就為大家分享一篇python爬蟲(chóng)之urllib,偽裝,超時(shí)設(shè)置,異常處理的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-12-12
Python selenium打開(kāi)瀏覽器指定端口實(shí)現(xiàn)接續(xù)操作
這篇文章主要為大家詳細(xì)介紹了Python selenium如何實(shí)現(xiàn)打開(kāi)瀏覽器指定端口后進(jìn)行接續(xù)操作,文中的示例代碼講解詳細(xì),有需要的小伙伴可以了解下2025-05-05

