Skip to content

Commit 56379a1

Browse files
committed
Adding support for audio files
1 parent cf15fcc commit 56379a1

File tree

6 files changed

+87
-2
lines changed

6 files changed

+87
-2
lines changed

AUTHORS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ alphabetical order):
3636
- Keith Feldman
3737
- Keith Johnson
3838
- Kevin Murray
39-
- Lucas Cimon
39+
- Lucas Cimon (@Lucas-C)
4040
- Lukas Vacek
4141
- Luke Cyca (@lukecyca)
4242
- Mate Lakat

src/sigal/audio.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Copyright (c) 2013 - Christophe-Marie Duquesne
2+
# Copyright (c) 2013-2023 - Simon Conseil
3+
# Copyright (c) 2021 - Keith Feldman
4+
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to
7+
# deal in the Software without restriction, including without limitation the
8+
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9+
# sell copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
12+
# The above copyright notice and this permission notice shall be included in
13+
# all copies or substantial portions of the Software.
14+
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20+
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21+
# IN THE SOFTWARE.
22+
23+
from os.path import dirname, join
24+
25+
from . import utils
26+
from .utils import is_valid_html5_audio
27+
28+
AUDIO_THUMB_FILE = join(dirname(__file__), "audio_file.png")
29+
30+
31+
def process_audio(media):
32+
"""Process an audio file: create thumbnail."""
33+
settings = media.settings
34+
35+
with utils.raise_if_debug() as status:
36+
utils.copy(media.src_path, media.dst_path, symlink=settings["orig_link"])
37+
38+
if settings["make_thumbs"]:
39+
utils.copy(AUDIO_THUMB_FILE, media.thumb_path)
40+
41+
return status.value

src/sigal/audio_file.png

1.76 KB
Loading

src/sigal/gallery.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,13 @@
5353
copy,
5454
get_mime,
5555
get_mod_date,
56+
is_valid_html5_audio,
5657
is_valid_html5_video,
5758
read_markdown,
5859
should_reprocess_album,
5960
url_from_path,
6061
)
62+
from .audio import process_audio
6163
from .video import process_video
6264
from .writer import AlbumListPageWriter, AlbumPageWriter
6365

@@ -345,6 +347,32 @@ def date(self):
345347
return self._get_file_date()
346348

347349

350+
class Audio(Media):
351+
"""Gather all informations on an audio file."""
352+
353+
type = "audio"
354+
355+
def __init__(self, filename, path, settings):
356+
super().__init__(filename, path, settings)
357+
self.mime = get_mime(self.src_ext)
358+
359+
@cached_property
360+
def date(self):
361+
"""The date from the Date metadata if available, or from the file date."""
362+
if "date" in self.meta:
363+
try:
364+
self.logger.debug(
365+
"Reading date from image metadata : %s", self.src_filename
366+
)
367+
return datetime.fromisoformat(self.meta["date"][0])
368+
except Exception:
369+
self.logger.debug(
370+
"Reading date from image metadata failed : %s", self.src_filename
371+
)
372+
# If no date is found in the metadata, return the file date.
373+
return self._get_file_date()
374+
375+
348376
class Album:
349377
"""Gather all informations on an album.
350378
@@ -403,6 +431,8 @@ def __init__(self, path, settings, dirnames, filenames, gallery):
403431
media = Image(f, self.path, settings)
404432
elif ext.lower() in settings["video_extensions"]:
405433
media = Video(f, self.path, settings)
434+
elif ext.lower() in settings["audio_extensions"]:
435+
media = Audio(f, self.path, settings)
406436

407437
# Allow modification of the media, including overriding the class
408438
# type for the media.
@@ -964,6 +994,8 @@ def process_file(media):
964994
processor = process_image
965995
elif media.type == "video":
966996
processor = process_video
997+
elif media.type == "audio":
998+
processor = process_audio
967999

9681000
# Allow overriding of the processor
9691001
result = signals.process_file.send(media, processor=processor)

src/sigal/settings.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@
8787
"video_format": "webm",
8888
"video_always_convert": False,
8989
"video_size": (480, 360),
90+
"audio_extensions": [".m4a", ".mp3", ".ogg", ".wav"],
9091
"watermark": "",
9192
"webm_options": ["-crf", "10", "-b:v", "1.6M", "-qmin", "4", "-qmax", "63"],
9293
"webm_options_second_pass": None,
@@ -121,6 +122,8 @@ def get_thumb(settings, filename):
121122

122123
if ext.lower() in settings["video_extensions"]:
123124
ext = ".jpg"
125+
if ext.lower() in settings["audio_extensions"]:
126+
ext = ".png" # extension of sigal.audio.AUDIO_THUMB_FILE
124127
return join(
125128
path,
126129
settings["thumb_dir"],

src/sigal/utils.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
logger = logging.getLogger(__name__)
3636
MD = None
3737
VIDEO_MIMES = {".mp4": "video/mp4", ".webm": "video/webm", ".ogv": "video/ogg"}
38+
AUDIO_MIMES = {".m4a": "audio/m4a", ".mp3": "audio/mpeg", ".ogg": "audio/ogg", ".wav": "audio/x-wav"}
3839

3940

4041
class Devnull:
@@ -146,9 +147,17 @@ def is_valid_html5_video(ext):
146147
return ext in VIDEO_MIMES.keys()
147148

148149

150+
def is_valid_html5_audio(ext):
151+
"""Checks if ext is a supported HTML5 video."""
152+
return ext in AUDIO_MIMES.keys()
153+
154+
149155
def get_mime(ext):
150156
"""Returns mime type for extension."""
151-
return VIDEO_MIMES[ext]
157+
mime_type = VIDEO_MIMES.get(ext) or AUDIO_MIMES.get(ext)
158+
if not mime_type:
159+
raise RuntimeError(f"Could not figure mime type, unknown file extension: {ext}")
160+
return mime_type
152161

153162

154163
def init_plugins(settings):

0 commit comments

Comments
 (0)