Cleanup; clead db dialog on no match
This commit is contained in:
parent
27c7df44c9
commit
fd2e21ba46
98
app.py
98
app.py
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from pydub import AudioSegment
|
|
||||||
from PyQt5.QtCore import Qt
|
from PyQt5.QtCore import Qt
|
||||||
from PyQt5.QtWidgets import QApplication, QDialog, QMainWindow
|
from PyQt5.QtWidgets import QApplication, QDialog, QMainWindow
|
||||||
from PyQt5.QtWidgets import QTableWidgetItem, QFileDialog, QListWidgetItem
|
from PyQt5.QtWidgets import QTableWidgetItem, QFileDialog, QListWidgetItem
|
||||||
@ -41,90 +40,6 @@ class RepeatedTimer:
|
|||||||
self.is_running = False
|
self.is_running = False
|
||||||
|
|
||||||
|
|
||||||
class Track:
|
|
||||||
def __init__(self, path):
|
|
||||||
self.path = path
|
|
||||||
|
|
||||||
audio = self.get_audio_segment(path)
|
|
||||||
self.start_gap = self.leading_silence(audio)
|
|
||||||
self.fade_at = self.fade_point(audio)
|
|
||||||
self.silence_at = self.trailing_silence(audio)
|
|
||||||
|
|
||||||
tag = TinyTag.get(path)
|
|
||||||
self.title = tag.title
|
|
||||||
self.artist = tag.artist
|
|
||||||
self.length = tag.duration * 1000
|
|
||||||
|
|
||||||
print(
|
|
||||||
f" path={self.path}"
|
|
||||||
f" length={self.length}"
|
|
||||||
f" start_gap={self.start_gap}"
|
|
||||||
f" fade_at={self.fade_at}"
|
|
||||||
f" silence_at={self.silence_at}"
|
|
||||||
f" title={self.title}"
|
|
||||||
f" artist={self.artist}"
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_audio_segment(self, path):
|
|
||||||
try:
|
|
||||||
if path.endswith('.mp3'):
|
|
||||||
return AudioSegment.from_mp3(path)
|
|
||||||
elif path.endswith('.flac'):
|
|
||||||
return AudioSegment.from_file(path, "flac")
|
|
||||||
except AttributeError:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def leading_silence(self, audio_segment, silence_threshold=-50.0,
|
|
||||||
chunk_size=10):
|
|
||||||
"""
|
|
||||||
Returns the millisecond/index that the leading silence ends.
|
|
||||||
audio_segment - the segment to find silence in
|
|
||||||
silence_threshold - the upper bound for how quiet is silent in dFBS
|
|
||||||
chunk_size - chunk size for interating over the segment in ms
|
|
||||||
|
|
||||||
https://github.com/jiaaro/pydub/blob/master/pydub/silence.py
|
|
||||||
"""
|
|
||||||
|
|
||||||
trim_ms = 0 # ms
|
|
||||||
assert chunk_size > 0 # to avoid infinite loop
|
|
||||||
while (
|
|
||||||
audio_segment[trim_ms:trim_ms + chunk_size].dBFS <
|
|
||||||
silence_threshold and trim_ms < len(audio_segment)):
|
|
||||||
trim_ms += chunk_size
|
|
||||||
|
|
||||||
# if there is no end it should return the length of the segment
|
|
||||||
return min(trim_ms, len(audio_segment))
|
|
||||||
|
|
||||||
def fade_point(self, audio_segment, fade_threshold=-20.0, chunk_size=10):
|
|
||||||
"""
|
|
||||||
Returns the millisecond/index of the point where the fade is down to
|
|
||||||
fade_threshold and doesn't get louder again.
|
|
||||||
audio_segment - the segment to find silence in
|
|
||||||
fade_threshold - the upper bound for how quiet is silent in dFBS
|
|
||||||
chunk_size - chunk size for interating over the segment in ms
|
|
||||||
"""
|
|
||||||
|
|
||||||
assert chunk_size > 0 # to avoid infinite loop
|
|
||||||
|
|
||||||
segment_length = audio_segment.duration_seconds * 1000 # ms
|
|
||||||
trim_ms = segment_length - chunk_size
|
|
||||||
while (
|
|
||||||
audio_segment[trim_ms:trim_ms + chunk_size].dBFS < fade_threshold
|
|
||||||
and trim_ms > 0):
|
|
||||||
trim_ms -= chunk_size
|
|
||||||
|
|
||||||
# if there is no trailing silence, return lenght of track (it's less
|
|
||||||
# the chunk_size, but for chunk_size = 10ms, this may be ignored)
|
|
||||||
return int(trim_ms)
|
|
||||||
|
|
||||||
def trailing_silence(self, audio_segment, silence_threshold=-50.0,
|
|
||||||
chunk_size=10):
|
|
||||||
return self.fade_point(audio_segment, silence_threshold, chunk_size)
|
|
||||||
|
|
||||||
|
|
||||||
ROOT = "/home/kae/music/"
|
|
||||||
|
|
||||||
|
|
||||||
def ms_to_mmss(ms, decimals=0):
|
def ms_to_mmss(ms, decimals=0):
|
||||||
if not ms:
|
if not ms:
|
||||||
return "-"
|
return "-"
|
||||||
@ -175,19 +90,20 @@ class Window(QMainWindow, Ui_MainWindow):
|
|||||||
row = self.playlist.currentRow()
|
row = self.playlist.currentRow()
|
||||||
print(f"Play id={self.playlist.item(row, 0).text()}")
|
print(f"Play id={self.playlist.item(row, 0).text()}")
|
||||||
|
|
||||||
print("play selected")
|
|
||||||
|
|
||||||
def selectFile(self):
|
def selectFile(self):
|
||||||
dlg = QFileDialog()
|
dlg = QFileDialog()
|
||||||
dlg.setFileMode(QFileDialog.ExistingFile)
|
dlg.setFileMode(QFileDialog.ExistingFile)
|
||||||
dlg.setViewMode(QFileDialog.Detail)
|
dlg.setViewMode(QFileDialog.Detail)
|
||||||
|
ROOT = "/home/kae/music/"
|
||||||
dlg.setDirectory(ROOT)
|
dlg.setDirectory(ROOT)
|
||||||
dlg.setNameFilter("Music files (*.flac *.mp3)")
|
dlg.setNameFilter("Music files (*.flac *.mp3)")
|
||||||
|
|
||||||
if dlg.exec_():
|
if dlg.exec_():
|
||||||
for fname in dlg.selectedFiles():
|
pass
|
||||||
track = Track(fname)
|
# TODO Add to database
|
||||||
self.add_to_playlist(track)
|
# for fname in dlg.selectedFiles():
|
||||||
|
# track = Track(fname)
|
||||||
|
# self.add_to_playlist(track)
|
||||||
|
|
||||||
def add_to_playlist(self, track):
|
def add_to_playlist(self, track):
|
||||||
"""
|
"""
|
||||||
@ -224,8 +140,8 @@ class DbDialog(QDialog):
|
|||||||
def chars_typed(self, s):
|
def chars_typed(self, s):
|
||||||
if len(s) >= 3:
|
if len(s) >= 3:
|
||||||
matches = Tracks.search_titles(s)
|
matches = Tracks.search_titles(s)
|
||||||
|
self.ui.listWidget.clear()
|
||||||
if matches:
|
if matches:
|
||||||
self.ui.listWidget.clear()
|
|
||||||
for track in matches:
|
for track in matches:
|
||||||
t = QListWidgetItem()
|
t = QListWidgetItem()
|
||||||
t.setText(
|
t.setText(
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user