Add fix incorrect play duration

This commit is contained in:
2024-06-26 12:11:09 +08:00
parent bc34a4f839
commit b2ea5ddd8d
3 changed files with 55 additions and 4 deletions

View File

@@ -1,7 +1,11 @@
from argparse import ArgumentParser from argparse import ArgumentParser
from os.path import join from os.path import join
from . import _ from . import _
from .audio import prepare_audio_map, generate_audio_report from .audio import (
prepare_audio_map,
generate_audio_report,
fix_audio_report_library,
)
from .cache import IdRelativeCache from .cache import IdRelativeCache
from .config import Config from .config import Config
from .db import PlaybackReportingDb, LibraryDb, JellyfinDb from .db import PlaybackReportingDb, LibraryDb, JellyfinDb
@@ -15,9 +19,12 @@ p.add_argument("--jellyfin-data-dir", help=_("The path to jellyfin data director
p.add_argument("--output-dir", help=_("The directory for output files.")) p.add_argument("--output-dir", help=_("The directory for output files."))
p.add_argument("--ask-page-size", help=_("Specify maximum items to display in one page."), type=int) # noqa: E501 p.add_argument("--ask-page-size", help=_("Specify maximum items to display in one page."), type=int) # noqa: E501
p.add_argument("--jellyfin-db", help=_("The path to jellyfin.db")) p.add_argument("--jellyfin-db", help=_("The path to jellyfin.db"))
p.add_argument("--fix", help=_("Fix incorrect play duration."), action='store_true', default=False) # noqa: E501
arg = p.parse_intermixed_args() arg = p.parse_intermixed_args()
cfg = Config(arg.config, arg) cfg = Config(arg.config, arg)
with PlaybackReportingDb(cfg.playback_reporting_db) as pdb: with PlaybackReportingDb(cfg.playback_reporting_db) as pdb:
if arg.fix:
fix_audio_report_library(pdb)
with LibraryDb(cfg.library_db) as ldb: with LibraryDb(cfg.library_db) as ldb:
with IdRelativeCache(cfg.output_dir) as icache: with IdRelativeCache(cfg.output_dir) as icache:
with JellyfinDb(cfg.jellyfin_db) as jdb: with JellyfinDb(cfg.jellyfin_db) as jdb:
@@ -30,4 +37,5 @@ with PlaybackReportingDb(cfg.playback_reporting_db) as pdb:
output = join(cfg.output_dir, 'audio', username) output = join(cfg.output_dir, 'audio', username)
maxDate = u['MaxDate'] maxDate = u['MaxDate']
minDate = u['MinDate'] minDate = u['MinDate']
generate_audio_report(pdb, re[0], re[1], re[2], output, userid) generate_audio_report(
pdb, re[0], re[1], re[2], output, userid)

View File

@@ -8,7 +8,7 @@ from datetime import datetime
from re import compile from re import compile
from os import makedirs from os import makedirs
from os.path import join from os.path import join
from math import floor from math import ceil, floor
ITEMNAME_PATTERN = compile(r'(?P<album_artist>.*) - (?P<track>.*) \((?P<album>.*)\)') # noqa: E501 ITEMNAME_PATTERN = compile(r'(?P<album_artist>.*) - (?P<track>.*) \((?P<album>.*)\)') # noqa: E501
@@ -405,3 +405,31 @@ def generate_audio_report(pdb: PlaybackReportingDb, itemMap, rowMap, albumMap,
for artist in alArtCountMap: for artist in alArtCountMap:
count = alArtCountMap[artist] count = alArtCountMap[artist]
alAr.write(artist, count['count'], count['play_count'], format_duration(count['duration']), count['duration']) # noqa: E501 alAr.write(artist, count['count'], count['play_count'], format_duration(count['duration']), count['duration']) # noqa: E501
def fix_audio_report_library(pdb: PlaybackReportingDb):
clients = pdb.get_client_devices()
for client in clients:
clientName = client['ClientName']
deviceName = client['DeviceName']
prev = None
offset = 0
data = pdb.get_activitys(offset, itemType='Audio',
clientName=clientName,
deviceName=deviceName)
while len(data) > 0:
for i in data:
if prev is None:
prev = i
continue
delta = ceil(parse_time(
i['DateCreated']) - parse_time(prev['DateCreated']))
dur = prev['PlayDuration']
if delta < dur - 1:
print(f'Change song(id={prev["rowid"]}) play duration from {dur} to {delta}') # noqa: E501
pdb.update_playduration(prev["rowid"], delta)
prev = i
offset += len(data)
data = pdb.get_activitys(offset, itemType='Audio',
clientName=clientName,
deviceName=deviceName)

View File

@@ -21,7 +21,8 @@ class PlaybackReportingDb:
def get_activitys(self, offset: int = 0, limit: int = 100, def get_activitys(self, offset: int = 0, limit: int = 100,
itemType: str = None, userId: str = None, itemType: str = None, userId: str = None,
startTime: float = None, endTime: float = None): startTime: float = None, endTime: float = None,
clientName: str = None, deviceName: str = None):
where_sqls = [] where_sqls = []
where_sql = '' where_sql = ''
args = [] args = []
@@ -37,6 +38,12 @@ class PlaybackReportingDb:
if endTime is not None: if endTime is not None:
where_sqls.append('DateCreated <= ?') where_sqls.append('DateCreated <= ?')
args.append(format_time(endTime)) args.append(format_time(endTime))
if clientName is not None:
where_sqls.append("ClientName = ?")
args.append(clientName)
if deviceName is not None:
where_sqls.append("DeviceName = ?")
args.append(deviceName)
if len(where_sqls): if len(where_sqls):
where_sql = ' WHERE ' + " AND ".join(where_sqls) where_sql = ' WHERE ' + " AND ".join(where_sqls)
args.append(limit) args.append(limit)
@@ -45,6 +52,11 @@ class PlaybackReportingDb:
cur.row_factory = sqlite3.Row cur.row_factory = sqlite3.Row
return [dict(i) for i in cur.fetchall()] return [dict(i) for i in cur.fetchall()]
def get_client_devices(self):
cur = self._db.execute("SELECT ClientName, DeviceName FROM PlaybackActivity GROUP BY ClientName, DeviceName;") # noqa: E501
cur.row_factory = sqlite3.Row
return [dict(i) for i in cur.fetchall()]
def get_users(self, itemType: str = None): def get_users(self, itemType: str = None):
where_sql = '' where_sql = ''
args = [] args = []
@@ -55,6 +67,9 @@ class PlaybackReportingDb:
cur.row_factory = sqlite3.Row cur.row_factory = sqlite3.Row
return [dict(i) for i in cur.fetchall()] return [dict(i) for i in cur.fetchall()]
def update_playduration(self, rowid: int, duration: int):
self._db.execute("UPDATE PlaybackActivity SET PlayDuration = ? WHERE rowid = ?;", [duration, rowid]) # noqa: E501
class LibraryDb: class LibraryDb:
def __init__(self, fn: str): def __init__(self, fn: str):