Files
2026-07-13 12:35:09 +08:00

209 lines
7.1 KiB
Python

# -*- coding: utf-8 -*-
"""
@Time : 2023/4/10/010 11:10
@Author : 李子
@Url : https://github.com/kslz
"""
from PySide6 import QtCore
from PySide6.QtCore import Signal, QThread
from PySide6.QtWidgets import QPushButton
from utils.tools import *
class FastOutputSoundBTN(QPushButton):
def __init__(self, text, info_id, parent):
super().__init__(text, parent)
self.info_id = info_id
self.clicked.connect(self.fast_output_sound)
# self.setText("快速导出")
# info = Info.get_by_id(self.info_id)
# wav_path = info.info_raw_file_path
# start_time = info.info_start_time
# end_time = info.info_end_time
def fast_output_sound(self):
info = Info.get_by_id(self.info_id)
wav_path = info.info_raw_file_path
start_time = info.info_start_time
end_time = info.info_end_time
output_name = str(self.info_id) + ".wav"
fast_output_sound(wav_path, start_time, end_time, output_name)
class DeleteBTN(QPushButton):
def __init__(self, text, info_id, parent, info_is_del):
super().__init__(text, parent)
self.info_id = info_id
self.info_is_del = info_is_del
if self.info_is_del == False:
self.setText("删除")
else:
self.setText("恢复")
self.clicked.connect(self.change_is_del_sound)
def change_is_del_sound(self):
# 肯定是伪删除
new_is_del = True if self.info_is_del == False else False
Info.update(info_is_del=new_is_del).where(Info.info_id == self.info_id).execute()
self.info_is_del = new_is_del
if self.info_is_del == False:
self.setText("删除")
else:
self.setText("恢复")
class PlaySoundBTN(QPushButton):
class PlaySoundThread(QtCore.QThread):
update_signal = Signal(str, bool)
# stop_thread_signal = Signal()
def __init__(self, wav_path, start_time, end_time):
super().__init__()
# self.stop_flag = False
# self.stop_thread_signal.connect(self.stop_thread)
self.wav_path = wav_path
self.start_time = start_time
self.end_time = end_time
def run(self):
self.update_signal.emit("播放中", False)
play_by_ffmpeg(self.wav_path, self.start_time, self.end_time)
self.update_signal.emit("试听", True)
# def stop_thread(self):
# self.stop_flag = True
# print("收到停止信号")
# self.wait()
def __init__(self, text, info_id, parent):
super().__init__(text, parent)
self.info_id = info_id
self.clicked.connect(self.play_or_stop_sound)
info = Info.get_by_id(self.info_id)
wav_path = info.info_raw_file_path
start_time = info.info_start_time
end_time = info.info_end_time
# self.thread1 = QThread(self) # 创建一个线程 不行 没用明白,先这样吧
self.play_thread = self.PlaySoundThread(wav_path, start_time, end_time) # 实例化线程类
# self.play_thread.moveToThread(self.thread1) # 将类移动到线程中运行
# self.thread1.started.connect(self.play_thread.run)
self.play_thread.update_signal.connect(lambda text, is_enabled: self.set_text(text, is_enabled))
def play_or_stop_sound(self):
# 多线程避免阻塞界面
if self.text() == "试听":
self.play_thread.start()
else:
# 终止播放失败
# self.play_thread.stop_thread_signal.emit()
# self.play_thread.exit()
# self.set_text("试听", True)
pass
def set_text(self, text, is_enabled):
self.setText(text)
# self.setEnabled(is_enabled)
class BianJiBTN(QPushButton):
on_clicked = Signal(int)
def __init__(self, text, info_id):
super().__init__(text=text)
self.info_id = info_id
self.clicked.connect(self.button_clicked)
def button_clicked(self):
self.on_clicked.emit(self.info_id)
class AudioButton(QPushButton):
def __init__(self, wav_path, start_time, end_time, parent=None):
super().__init__(parent)
self.setText("试听")
self.audio_thread = None
self.wav_path = wav_path
self.start_time = start_time
self.end_time = end_time
# 连接按钮点击事件的槽函数
self.clicked.connect(self.on_button_clicked)
def on_button_clicked(self):
if self.audio_thread is not None and self.audio_thread.is_playing:
# 如果音频正在播放,停止播放
# print("停止播放")
self.audio_thread.stop()
self.audio_thread.wait()
self.audio_thread = None
self.setText("试听")
else:
# 如果音频没有在播放,开始播放
self.audio_thread = AudioThread(self.wav_path, self.start_time, self.end_time)
self.audio_thread.finished.connect(self.on_audio_finished)
self.audio_thread.start()
self.setText("停止")
def on_audio_finished(self):
self.audio_thread = None
self.setText("试听")
# 自定义的音频播放线程
class AudioThread(QThread):
finished = Signal() # 定义一个信号,用于通知播放完成
def __init__(self, wav_path, start_time, end_time, parent=None):
super().__init__(parent)
self.is_playing = False
self.wav_path = wav_path
self.start_time = start_time
self.end_time = end_time
def run(self):
self.is_playing = True
# play_by_ffmpeg(self.wav_path, self.start_time, self.end_time)
# 如果用函数形式调用,执行self.audio_thread.terminate()的时候声音就会卡几秒才停,直接写代码就可以秒停,原因未知
wav_path = self.wav_path
start_time = self.start_time
end_time = self.end_time
duration = (end_time - start_time) / 1000
start_time = start_time / 1000
# 从长音频文件中提取指定时间段的音频
output = (
ffmpeg
.input(wav_path, ss=start_time, t=duration)
# .filter("loudnorm", I="-23", dual_mono="true") # 归一化
.output('pipe:', format='wav', ar=44100)
.run(capture_stdout=True)
)
# 播放输出的音频
self.process = subprocess.Popen(['ffplay', "-nodisp", "-autoexit", '-'], stdin=subprocess.PIPE)
self.process.communicate(output[0])
self.is_playing = False
self.finished.emit() # 发送播放完成的信号
def stop(self):
if self.process and self.process.poll() is None: # 检查子进程是否在运行
self.process.terminate() # 终止子进程
class AudioNowButton(AudioButton):
def __init__(self, wav_path, start_time, end_time, parent=None):
super().__init__(wav_path, start_time, end_time, parent)
self.clicked.disconnect(super().on_button_clicked)
def on_button_clicked_new(self, start_time, end_time):
self.start_time = int(start_time)
self.end_time = int(end_time)
self.on_button_clicked()