Compare commits
1 Commits
4c13322936
...
13df69adb4
| Author | SHA1 | Date | |
|---|---|---|---|
| 13df69adb4 |
@@ -122,24 +122,37 @@ class BrowserService:
|
||||
|
||||
@staticmethod
|
||||
def get_media_info(file_path: Path) -> dict:
|
||||
"""Get duration and bitrate of a media file (header-only read).
|
||||
"""Get duration, bitrate, and title of a media file (header-only read).
|
||||
|
||||
Args:
|
||||
file_path: Path to the media file.
|
||||
|
||||
Returns:
|
||||
Dict with 'duration' (float or None) and 'bitrate' (int or None).
|
||||
Dict with 'duration' (float or None), 'bitrate' (int or None),
|
||||
and 'title' (str or None).
|
||||
"""
|
||||
result = {"duration": None, "bitrate": None}
|
||||
result = {"duration": None, "bitrate": None, "title": None}
|
||||
if not HAS_MUTAGEN:
|
||||
return result
|
||||
try:
|
||||
audio = MutagenFile(str(file_path))
|
||||
audio = MutagenFile(str(file_path), easy=True)
|
||||
if audio is not None and hasattr(audio, "info"):
|
||||
if hasattr(audio.info, "length"):
|
||||
result["duration"] = round(audio.info.length, 2)
|
||||
if hasattr(audio.info, "bitrate") and audio.info.bitrate:
|
||||
result["bitrate"] = audio.info.bitrate
|
||||
if audio is not None and hasattr(audio, "tags") and audio.tags:
|
||||
tags = audio.tags
|
||||
title = None
|
||||
artist = None
|
||||
if "title" in tags:
|
||||
title = tags["title"][0] if isinstance(tags["title"], list) else tags["title"]
|
||||
if "artist" in tags:
|
||||
artist = tags["artist"][0] if isinstance(tags["artist"], list) else tags["artist"]
|
||||
if artist and title:
|
||||
result["title"] = f"{artist} \u2013 {title}"
|
||||
elif title:
|
||||
result["title"] = title
|
||||
except Exception:
|
||||
pass
|
||||
return result
|
||||
@@ -262,9 +275,11 @@ class BrowserService:
|
||||
info = BrowserService.get_media_info(item_path)
|
||||
item["duration"] = info["duration"]
|
||||
item["bitrate"] = info["bitrate"]
|
||||
item["title"] = info["title"]
|
||||
else:
|
||||
item["duration"] = None
|
||||
item["bitrate"] = None
|
||||
item["title"] = None
|
||||
|
||||
return {
|
||||
"folder_id": folder_id,
|
||||
|
||||
@@ -1705,10 +1705,10 @@ function renderBrowserList(items, container) {
|
||||
}
|
||||
row.appendChild(icon);
|
||||
|
||||
// Name
|
||||
// Name (show media title if available)
|
||||
const name = document.createElement('div');
|
||||
name.className = 'browser-list-name';
|
||||
name.textContent = item.name;
|
||||
name.textContent = item.title || item.name;
|
||||
row.appendChild(name);
|
||||
|
||||
// Bitrate
|
||||
@@ -1736,9 +1736,9 @@ function renderBrowserList(items, container) {
|
||||
row.appendChild(document.createElement('div'));
|
||||
}
|
||||
|
||||
// Tooltip on row when name is ellipsed
|
||||
// Tooltip: show filename when title is displayed, or when name is ellipsed
|
||||
row.addEventListener('mouseenter', () => {
|
||||
if (name.scrollWidth > name.clientWidth) {
|
||||
if (item.title || name.scrollWidth > name.clientWidth) {
|
||||
row.title = item.name;
|
||||
} else {
|
||||
row.title = '';
|
||||
@@ -1820,7 +1820,7 @@ function renderBrowserGrid(items, container) {
|
||||
|
||||
const name = document.createElement('div');
|
||||
name.className = 'browser-item-name';
|
||||
name.textContent = item.name;
|
||||
name.textContent = item.title || item.name;
|
||||
info.appendChild(name);
|
||||
|
||||
if (item.type !== 'folder') {
|
||||
@@ -1838,9 +1838,9 @@ function renderBrowserGrid(items, container) {
|
||||
|
||||
div.appendChild(info);
|
||||
|
||||
// Tooltip on card when name is ellipsed
|
||||
// Tooltip: show filename when title is displayed, or when name is ellipsed
|
||||
div.addEventListener('mouseenter', () => {
|
||||
if (name.scrollWidth > name.clientWidth || name.scrollHeight > name.clientHeight) {
|
||||
if (item.title || name.scrollWidth > name.clientWidth || name.scrollHeight > name.clientHeight) {
|
||||
div.title = item.name;
|
||||
} else {
|
||||
div.title = '';
|
||||
|
||||
Reference in New Issue
Block a user