-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstats.py
206 lines (181 loc) · 6.59 KB
/
stats.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
#!/usr/bin/env python3
"""
Music Stats Recorder
This script records statistics about the music library, such as the number and size of files,
and MPD server stats. It also provides extended statistics including the duration of audio and video files.
Dependencies:
- os
- sys
- math
- datetime
- pathlib
- python-mpd2
- moviepy.editor
- pydub.utils.mediainfo
- mutagen
Usage:
python stats.py [-e|--extended]
Optional arguments:
-e, --extended Include extended statistics with audio and video file durations.
"""
import os
import sys
import math
from datetime import datetime
from pathlib import Path
import mpd
from moviepy.editor import VideoFileClip
from pydub.utils import mediainfo
from mutagen.mp3 import MP3
from mutagen.mp4 import MP4
from mutagen.flac import FLAC
from mutagen.oggvorbis import OggVorbis
from mutagen.m4a import M4A
from mutagen.oggopus import OggOpus
def read_mpd_config():
"""
Function to read MPD configuration from mpd.conf file.
Returns:
- Dictionary containing MPD configuration.
"""
mpd_conf_paths = [
"/etc/mpd.conf",
"/etc/mpd/mpd.conf",
"/usr/local/etc/mpd.conf",
"~/.mpdconf",
"~/.config/mpd/mpd.conf"
]
for path in mpd_conf_paths:
full_path = os.path.expanduser(path)
if os.path.isfile(full_path):
config = {}
with open(full_path, 'r') as f:
for line in f:
if '=' in line:
key, value = line.strip().split('=', 1)
config[key.strip()] = value.strip()
return config
print("MPD configuration file (mpd.conf) not found in common locations.")
sys.exit(1)
# Read MPD server configuration from mpd.conf
mpd_config = read_mpd_config()
music_library = mpd_config.get('music_directory', '/var/lib/mpd/music')
mpd_host = mpd_config.get('bind_to_address', 'localhost')
mpd_port = mpd_config.get('port', '6600')
mpd_password = mpd_config.get('password', '') # Read password from mpd.conf
# Connect to MPD server
client = mpd.MPDClient()
client.connect(host=mpd_host, port=int(mpd_port))
if mpd_password:
client.password(mpd_password)
# Get MPD server stats
mpd_stats = client.stats()
def get_duration(filename):
"""
Function to get the duration of an audio or video file.
"""
try:
_, ext = os.path.splitext(filename)
if ext.lower() == ".mp3":
audio = MP3(filename)
duration = audio.info.length
elif ext.lower() == ".mp4":
video = VideoFileClip(filename)
duration = video.duration
elif ext.lower() == ".flac":
audio = FLAC(filename)
duration = audio.info.length
elif ext.lower() == ".ogg":
audio = OggVorbis(filename)
duration = audio.info.length
elif ext.lower() == ".m4a":
audio = M4A(filename)
duration = audio.info.length
elif ext.lower() == ".wma":
info = mediainfo(filename)
duration = float(info["duration"]) / 1000.0
elif ext.lower() == ".avi":
video = VideoFileClip(filename)
duration = video.duration
elif ext.lower() == ".opus":
audio = OggOpus(filename)
duration = audio.info.length
else:
return 0
return duration
except Exception as e:
print(f"Error getting duration of {filename}: {e}")
return 0
def format_time(seconds):
"""
Function to convert seconds to human-readable format (days, hours, minutes, seconds).
"""
days, seconds = divmod(seconds, 86400)
hours, seconds = divmod(seconds, 3600)
minutes, seconds = divmod(seconds, 60)
return f"{int(days)} days, {int(hours)} hours, {int(minutes)} minutes, {int(seconds)} seconds"
def convert_size(size_bytes):
"""
Function to convert bytes to a human-readable format (KB, MB, GB).
"""
if size_bytes == 0:
return "0B"
size_name = ("B", "KB", "MB", "GB")
i = int(math.floor(math.log(size_bytes, 1024)))
p = math.pow(1024, i)
s = round(size_bytes / p, 2)
return "%s %s" % (s, size_name[i])
def get_total_duration(base_dir):
"""
Function to get the total duration of audio and video files in a directory.
"""
total_duration = 0
filetype_durations = {}
for root, dirs, files in os.walk(base_dir):
for file in files:
filename = os.path.join(root, file)
duration = get_duration(filename)
if duration > 0:
total_duration += duration
_, ext = os.path.splitext(filename)
if ext.lower() not in filetype_durations:
filetype_durations[ext.lower()] = duration
else:
filetype_durations[ext.lower()] += duration
return total_duration, filetype_durations
extended = '-e' in sys.argv or '--extended' in sys.argv
stats_file = os.path.join(music_library, "stats")
date = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
with open(stats_file, "a") as f:
f.write(date + "\n")
f.write(str(mpd_stats) + "\n\n")
f.write(".flac files found in library:\t{}\t{}\n".format(
len(list(Path(music_library).rglob("*.flac"))),
convert_size(sum(f.stat().st_size for f in Path(music_library).rglob("*.flac")))
))
f.write(".mp3 files found in library: \t{}\t{}\n".format(
len(list(Path(music_library).rglob("*.mp3"))),
convert_size(sum(f.stat().st_size for f in Path(music_library).rglob("*.mp3")))
))
f.write(".opus files found in library: \t{}\t{}\n".format(
len(list(Path(music_library).rglob("*.opus"))),
convert_size(sum(f.stat().st_size for f in Path(music_library).rglob("*.opus")))
))
f.write(".ogg files found in library: \t{}\t{}\n".format(
len(list(Path(music_library).rglob("*.ogg"))),
convert_size(sum(f.stat().st_size for f in Path(music_library).rglob("*.ogg")))
))
f.write(".mp4 files found in library: \t{}\t{}\n".format(
len(list(Path(music_library).rglob("*.mp4"))),
convert_size(sum(f.stat().st_size for f in Path(music_library).rglob("*.mp4")))
))
if extended:
total_duration, filetype_durations = get_total_duration(music_library)
f.write("\nTotal duration of all valid audio and video files: {}\n".format(format_time(total_duration)))
f.write("Per-filetype durations:\n")
for ext, duration in filetype_durations.items():
f.write(f" {ext}: {format_time(duration)}\n")
print('-' * os.get_terminal_size().columns)
with open(stats_file, "r") as f:
print(f.read())
client.close()