Upload files to ''
This commit is contained in:
parent
188c5e8abb
commit
017519f1b5
126
sac.py
Normal file
126
sac.py
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
import os
|
||||||
|
from PyQt5.QtCore import QProcess, Qt
|
||||||
|
from PyQt5.QtWidgets import QApplication, QWidget, QGridLayout, QLabel, QLineEdit, QPushButton, QFileDialog, QMessageBox, QComboBox, QRadioButton
|
||||||
|
|
||||||
|
class SAC(QWidget):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.setWindowTitle('SAC - Simple Audio Converter')
|
||||||
|
self.source_file_btn = QPushButton('Browse')
|
||||||
|
self.dest_dir_btn = QPushButton('Browse')
|
||||||
|
self.convert_btn = QPushButton('Convert')
|
||||||
|
self.abort_btn = QPushButton('Abort')
|
||||||
|
self.out_codec_dropdown = QComboBox()
|
||||||
|
self.bitrate_dropdown = QComboBox()
|
||||||
|
self.stereo_radio = QRadioButton('Stereo')
|
||||||
|
self.mono_radio = QRadioButton('Mono')
|
||||||
|
self.source_file_input = QLineEdit()
|
||||||
|
self.dest_dir_input = QLineEdit()
|
||||||
|
|
||||||
|
self.out_codec_dropdown.addItems(['mp3', 'aac', 'wav', 'flac', 'opus'])
|
||||||
|
self.out_codec_dropdown.setCurrentText('mp3')
|
||||||
|
self.bitrate_dropdown.addItems(['64K', '128K', '256K', '320K'])
|
||||||
|
self.bitrate_dropdown.setCurrentText('128K')
|
||||||
|
self.stereo_radio.setChecked(True)
|
||||||
|
|
||||||
|
self.source_file_btn.clicked.connect(self.browse_source_file)
|
||||||
|
self.dest_dir_btn.clicked.connect(self.browse_dest_dir)
|
||||||
|
self.convert_btn.clicked.connect(self.convert_audio)
|
||||||
|
self.abort_btn.clicked.connect(self.abort_audio)
|
||||||
|
self.out_codec_dropdown.currentTextChanged.connect(self.toggle_bitrate)
|
||||||
|
self.source_file_input.setAcceptDrops(True)
|
||||||
|
self.dest_dir_input.setAcceptDrops(True)
|
||||||
|
|
||||||
|
layout = QGridLayout()
|
||||||
|
layout.addWidget(QLabel('Source File'), 0, 0), layout.addWidget(self.source_file_input, 0, 1), layout.addWidget(self.source_file_btn, 0, 2)
|
||||||
|
layout.addWidget(QLabel('Destination Directory'), 1, 0), layout.addWidget(self.dest_dir_input, 1, 1), layout.addWidget(self.dest_dir_btn, 1, 2)
|
||||||
|
layout.addWidget(QLabel('Output Codec'), 2, 0), layout.addWidget(self.out_codec_dropdown, 2, 1)
|
||||||
|
layout.addWidget(QLabel('Bitrate'), 3, 0), layout.addWidget(self.bitrate_dropdown, 3, 1)
|
||||||
|
layout.addWidget(QLabel('Channel'), 4, 0), layout.addWidget(self.stereo_radio, 4, 1), layout.addWidget(self.mono_radio, 4, 2)
|
||||||
|
layout.addWidget(self.convert_btn, 5, 0), layout.addWidget(self.abort_btn, 5, 1)
|
||||||
|
|
||||||
|
self.setLayout(layout)
|
||||||
|
self.process = None
|
||||||
|
self.abort_btn.setDisabled(True)
|
||||||
|
|
||||||
|
def browse_source_file(self):
|
||||||
|
filename, _ = QFileDialog.getOpenFileName(self, 'Select Source File', os.getenv('HOME'), 'Audio File (*.*)')
|
||||||
|
if filename:
|
||||||
|
self.source_file_input.setText(filename)
|
||||||
|
self.dest_dir_input.setText(os.path.dirname(filename))
|
||||||
|
|
||||||
|
def browse_dest_dir(self):
|
||||||
|
dirpath = QFileDialog.getExistingDirectory(self, 'Select Destination Directory', self.dest_dir_input.text())
|
||||||
|
if dirpath:
|
||||||
|
self.dest_dir_input.setText(dirpath)
|
||||||
|
|
||||||
|
def convert_audio(self):
|
||||||
|
input_path = self.source_file_input.text()
|
||||||
|
output_dir = self.dest_dir_input.text()
|
||||||
|
out_codec = self.out_codec_dropdown.currentText()
|
||||||
|
bitrate = self.bitrate_dropdown.currentText() if not out_codec in ['flac'] else ''
|
||||||
|
channel = '2' if self.stereo_radio.isChecked() else '1'
|
||||||
|
|
||||||
|
if not os.path.isfile(input_path) or not os.path.isdir(output_dir): return
|
||||||
|
|
||||||
|
output_filename = os.path.splitext(os.path.basename(input_path))[0] + '.' + out_codec
|
||||||
|
output_path = os.path.join(output_dir, output_filename)
|
||||||
|
|
||||||
|
if out_codec == 'opus':
|
||||||
|
cmd = f'ffmpeg -i "{input_path}" -ac {channel} -b:a {bitrate.lower()} -c:a libopus -application audio -strict -2 "{output_path}"'
|
||||||
|
elif out_codec == 'wav':
|
||||||
|
cmd = f'ffmpeg -i "{input_path}" -ac {channel} -c:a pcm_s16le "{output_path}"'
|
||||||
|
else:
|
||||||
|
cmd = f'ffmpeg -i "{input_path}" -ac {channel} "{output_path}"'
|
||||||
|
|
||||||
|
[btn.setDisabled(True) for btn in [self.convert_btn, self.source_file_btn, self.dest_dir_btn, self.out_codec_dropdown, self.bitrate_dropdown, self.stereo_radio, self.mono_radio]]
|
||||||
|
self.abort_btn.setDisabled(False)
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.process = QProcess()
|
||||||
|
self.process.setProcessChannelMode(QProcess.MergedChannels)
|
||||||
|
self.process.start(cmd)
|
||||||
|
if not self.process.waitForStarted():
|
||||||
|
self.show_error('Error', 'Failed to start process')
|
||||||
|
else:
|
||||||
|
while self.process.state() == QProcess.Running:
|
||||||
|
QApplication.processEvents()
|
||||||
|
if self.process.exitCode() == 0:
|
||||||
|
QMessageBox.information(self, 'Success', f'Audio file converted successfully: {output_path}')
|
||||||
|
else:
|
||||||
|
self.show_error('Error', f'Failed to convert audio file: {output_path}')
|
||||||
|
except Exception as e:
|
||||||
|
self.show_error('Error', str(e))
|
||||||
|
finally:
|
||||||
|
[btn.setDisabled(False) for btn in [self.convert_btn, self.source_file_btn, self.dest_dir_btn, self.out_codec_dropdown, self.bitrate_dropdown, self.stereo_radio, self.mono_radio]]
|
||||||
|
self.abort_btn.setDisabled(True)
|
||||||
|
|
||||||
|
def abort_audio(self):
|
||||||
|
self.process.terminate()
|
||||||
|
|
||||||
|
def toggle_bitrate(self):
|
||||||
|
is_opus = self.out_codec_dropdown.currentText() == 'opus'
|
||||||
|
self.bitrate_dropdown.setDisabled(not is_opus)
|
||||||
|
|
||||||
|
def show_error(self, title, message):
|
||||||
|
QMessageBox.critical(self, title, message)
|
||||||
|
|
||||||
|
def dragEnterEvent(self, event):
|
||||||
|
if event.mimeData().hasUrls():
|
||||||
|
event.acceptProposedAction()
|
||||||
|
|
||||||
|
def dropEvent(self, event):
|
||||||
|
if event.mimeData().hasUrls():
|
||||||
|
url = event.mimeData().urls()[0]
|
||||||
|
path = url.toLocalFile()
|
||||||
|
if os.path.isfile(path):
|
||||||
|
self.source_file_input.setText(path)
|
||||||
|
self.dest_dir_input.setText(os.path.dirname(path))
|
||||||
|
event.acceptProposedAction()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app = QApplication([])
|
||||||
|
sac = SAC()
|
||||||
|
sac.show()
|
||||||
|
app.exec_()
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user