Skip to content

Commit

Permalink
fix bug & add drop file feature
Browse files Browse the repository at this point in the history
1. fix `name.HD.Chinese.mp4` like file path error
2. add drop file feature:
    drop file and automatically extract name & path
3. update README
  • Loading branch information
taseikyo committed Dec 14, 2019
1 parent c3d41f0 commit 860bbc9
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 46 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ A simple [Cat Calendar](cat-calendar) image generator that uses the "www.dutanga

### FFmpeg Helper

[FFmpeg Helper](ffmpeg-helper) is a FFmpeg-based tool to cut/merge video.
[FFmpeg Helper](ffmpeg-helper) is a FFmpeg-based tool to cut/merge video and extract audio from the video.

<div align="center">
<img src="images/ffmpeg-helper.gif" alt="FFmpeg Helper" title="FFmpeg Helper" />
Expand Down
4 changes: 3 additions & 1 deletion ffmpeg-helper/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
## FFmpeg Helper

a FFmpeg-based tool to cut/merge video
a FFmpeg-based tool to cut/merge video and extract audio from the video.

### cut video

mode:
- DURATION_MODE
Expand Down
2 changes: 1 addition & 1 deletion ffmpeg-helper/ffmpeg-helper/mwin.ui
Original file line number Diff line number Diff line change
Expand Up @@ -307,4 +307,4 @@
<include location="res.qrc"/>
</resources>
<connections/>
</ui>
</ui>
106 changes: 63 additions & 43 deletions ffmpeg-helper/src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,43 +24,61 @@ def __init__(self, parent=None):
super(MWin, self).__init__(parent)
self.setupUi(self)

self.cut_file_path = ''
self.merge_files_path = ''
self.cut_file_path = ""
self.merge_files_path = ""

self.mode = DURATION_MODE

self.cmder_thread = Cmder('')
self.cmder_thread = Cmder("")
self.cmder_thread.log.connect(self.log_display)
self.cmder_thread.done.connect(self.log_display)
self.cmder_thread.error.connect(self.error_handler)

# accept drop event
self.setAcceptDrops(True)

def dragEnterEvent(self, e):
allow_type = ["mp4", "avi", "mkv", "ts", "rmvb", "rm", "mov"]
_, ext = os.path.splitext(e.mimeData().text())
if ext[1:] in allow_type:
e.accept()
else:
e.ignore()

def dropEvent(self, e):
# e.mimeData().text() = file:///F:videio/xxx.mp4
filename = e.mimeData().text()[8:]
self.cut_file_path = filename
self.filename_label.setText(os.path.basename(filename))
self.log_edit.setPlainText("")

@pyqtSlot()
def on_select_file_btn_clicked(self):
filename, filetype = QFileDialog.getOpenFileName(self,
'choose file',
'.', '*')
filename, filetype = QFileDialog.getOpenFileName(self, "choose file", "", "*")
if not filename:
return

self.cut_file_path = filename
self.filename_label.setText(os.path.basename(filename))
self.log_edit.setPlainText('')
self.log_edit.setPlainText("")

def on_duration_check_stateChanged(self, mode):
if mode == 0:
self.mode = ENDTIME_MODE
self.radio_label.setText('End Time:')
self.radio_label.setText("End Time:")
else:
self.mode = DURATION_MODE
self.radio_label.setText('Duration:')
self.radio_label.setText("Duration:")

@pyqtSlot()
def on_start_btn_clicked(self):
if not self.cut_file_path:
return

start_offset_raw = self.start_time_edit.text().replace(':', ':').replace(' ', '')
end_offset_raw = self.end_time_edit.text().replace(':', ':').replace(' ', '')
start_offset_raw = (
self.start_time_edit.text().replace(":", ":").replace(" ", "")
)
end_offset_raw = self.end_time_edit.text().replace(":", ":").replace(" ", "")

start_offset = self.time_format_check(start_offset_raw)
end_offset = self.time_format_check(end_offset_raw)
Expand All @@ -71,9 +89,8 @@ def on_start_btn_clicked(self):
if (not start_offset) or (not end_offset):
return

tmp = self.filename_label.text().split('.')
out_file = os.path.split(self.cut_file_path)[
0] + '/' + tmp[0] + '_cut.' + tmp[1]
tmp = os.path.splitext(self.cut_file_path)
out_file = f"{tmp[0]}_cut{tmp[1]}"

if self.mode == ENDTIME_MODE:
if not self.time_interval_check(start_offset, end_offset):
Expand All @@ -98,12 +115,12 @@ def on_extract_btn_clicked(self):
self.cmder_thread.start()

def time_format_check(self, time_raw):
'''check `time_raw` is legal
"""check `time_raw` is legal
and return a legal time
'''
"""
time_legal = []
carry = 0
for x in time_raw.split(':')[::-1]:
for x in time_raw.split(":")[::-1]:
try:
tmp = int(x) + carry
if tmp > 59:
Expand All @@ -113,37 +130,38 @@ def time_format_check(self, time_raw):
carry = 0
time_legal.append(str(tmp))
except:
return ''
return ""
if carry:
time_legal.append(str(carry))
return ':'.join(time_legal[::-1])
return ":".join(time_legal[::-1])

def time_interval_check(self, time_start, time_end):
'''check end > start
'''
"""check end > start
"""
start, end = 0, 0
base = 1
for x in time_start.split(':')[::-1]:
start += base*int(x)
for x in time_start.split(":")[::-1]:
start += base * int(x)
base *= 10
base = 1
for x in time_end.split(':')[::-1]:
end += base*int(x)
for x in time_end.split(":")[::-1]:
end += base * int(x)
base *= 10
return start < end

@pyqtSlot()
def on_select_files_btn_clicked(self):
files, ok = QFileDialog.getOpenFileNames(self, 'choose file',
'.', 'MP4 Files (*.mp4)')
files, ok = QFileDialog.getOpenFileNames(
self, "choose file", ".", "MP4 Files (*.mp4)"
)
if not ok:
return
self.merge_files_path = files

self.tableWidget.clearContents()
self.tableWidget.setRowCount(0)
self.tableWidget.setColumnCount(1)
self.tableWidget.setHorizontalHeaderLabels(['Merge Filenames'])
self.tableWidget.setHorizontalHeaderLabels(["Merge Filenames"])
self.tableWidget.horizontalHeader().setStretchLastSection(True)

for x in range(len(files)):
Expand All @@ -161,8 +179,8 @@ def on_start_merge_btn_clicked(self):
# transform
for x in self.merge_files_path:
tmp = os.path.split(x)
out_file = tmp[0] + '/' + tmp[1].split('.')[0] + '.ts'
ts_files.append(tmp[1].split('.')[0] + '.ts')
out_file = tmp[0] + "/" + tmp[1].split(".")[0] + ".ts"
ts_files.append(tmp[1].split(".")[0] + ".ts")
cmd = f'ffmpeg -i "{x}" -acodec copy -vcodec copy -absf aac_adtstoasc -y "{out_file}"'
try:
with os.popen(cmd) as f:
Expand All @@ -181,50 +199,52 @@ def on_start_merge_btn_clicked(self):
print(f.read())
except Exception as e:
print(e)
os.remove(f'{ts_files[0]}_merge.mp4')
os.remove(f"{ts_files[0]}_merge.mp4")
return

# for x in ts_files:
# os.remove(x)

os.chdir(cwd)


def log_display(self, text):
old_text = self.log_edit.toPlainText()
self.log_edit.setPlainText(f'{old_text}{text}')
self.log_edit.setPlainText(f"{old_text}{text}")

scrollbar = self.log_edit.verticalScrollBar()
if scrollbar:
scrollbar.setSliderPosition(scrollbar.maximum())

def error_handler(self, emsg):
QMessageBox.warning(self, 'FFmpeg Helper', emsg, QMessageBox.Ok)
QMessageBox.warning(self, "FFmpeg Helper", emsg, QMessageBox.Ok)

class Cmder(QThread):

class Cmder(QThread):
log = pyqtSignal(str)
error = pyqtSignal(str)
done = pyqtSignal(str)

def __init__(self, cmd):
super().__init__()
self.cmd = cmd
def run(self):

def run(self):
try:
p = subprocess.Popen(self.cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
for line in iter(p.stdout.readline, b''):
p = subprocess.Popen(
self.cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
)
for line in iter(p.stdout.readline, b""):
try:
line = line.decode('utf-8')
line = line.decode("utf-8")
except:
line = line.decode('gbk')
line = line.decode("gbk")
self.log.emit(line)
except Exception as e:
self.error.emit(str(e))
self.done.emit('done')
self.done.emit("done")


if __name__ == '__main__':
if __name__ == "__main__":
app = QApplication(sys.argv)
w = MWin()
w.show()
Expand Down
Binary file modified images/ffmpeg-helper.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 860bbc9

Please sign in to comment.