Skip to content

Commit

Permalink
Merge pull request #294 from bohning/tags_to_video_file
Browse files Browse the repository at this point in the history
Write tags (and artwork, if selected) also to the video file (mp4 only).
  • Loading branch information
bohning authored Sep 22, 2024
2 parents d3bba12 + 7a0bcf6 commit 5cfaa6d
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 17 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
- Comments can now be posted on songs. Each comment includes a message and a rating.
Ratings can be negative, neutral, or positive, with neutral being the default.
- The VP9 codec can be excluded for mp4 video containers (see _Settings_).
- Tags (and artwork, if selected) are now also written to the video file (mp4 only).

## Developer notes

Expand Down
2 changes: 2 additions & 0 deletions src/usdb_syncer/download_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class VideoOptions:
reencode_format: settings.VideoCodec | None
max_resolution: settings.VideoResolution
max_fps: settings.VideoFps
embed_artwork: bool

def ytdl_format(self) -> str:
fmt = self.format.ytdl_format()
Expand Down Expand Up @@ -116,6 +117,7 @@ def _video_options() -> VideoOptions | None:
),
max_resolution=settings.get_video_resolution(),
max_fps=settings.get_video_fps(),
embed_artwork=settings.get_video_embed_artwork(),
)


Expand Down
44 changes: 29 additions & 15 deletions src/usdb_syncer/gui/forms/SettingsDialog.ui
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,20 @@
</property>
</widget>
</item>
<item row="0" column="0">
<item row="2" column="0">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0" rowspan="2">
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
Expand Down Expand Up @@ -357,7 +370,7 @@
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<item row="4" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox_reencode_video">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
Expand Down Expand Up @@ -401,6 +414,20 @@
</layout>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_video_embed_artwork">
<property name="text">
<string>Embed artwork:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QCheckBox" name="checkBox_video_embed_artwork">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
</item>
Expand Down Expand Up @@ -505,19 +532,6 @@
</widget>
</widget>
</item>
<item row="2" column="0">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
Expand Down
2 changes: 2 additions & 0 deletions src/usdb_syncer/gui/settings_dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ def _load_settings(self) -> None:
self.comboBox_fps.setCurrentIndex(
self.comboBox_fps.findData(settings.get_video_fps())
)
self.checkBox_video_embed_artwork.setChecked(settings.get_video_embed_artwork())
self.groupBox_background.setChecked(settings.get_background())
self.checkBox_background_always.setChecked(settings.get_background_always())

Expand Down Expand Up @@ -150,6 +151,7 @@ def _save_settings(self) -> bool:
settings.set_video_reencode(self.groupBox_reencode_video.isChecked())
settings.set_video_resolution(self.comboBox_videoresolution.currentData())
settings.set_video_fps(self.comboBox_fps.currentData())
settings.set_video_embed_artwork(self.checkBox_video_embed_artwork.isChecked())
settings.set_background(self.groupBox_background.isChecked())
settings.set_background_always(self.checkBox_background_always.isChecked())
if self._path_template:
Expand Down
9 changes: 9 additions & 0 deletions src/usdb_syncer/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ class SettingKey(Enum):
VIDEO_FORMAT_NEW = "downloads/video_format_new"
VIDEO_RESOLUTION_MAX = "downloads/video_resolution_max"
VIDEO_FPS_MAX = "downloads/video_fps_max"
VIDEO_EMBED_ARTWORK = "downloads/video_embed_artwork"
COVER = "downloads/cover"
COVER_MAX_SIZE = "downloads/cover_max_size"
BACKGROUND = "downloads/background"
Expand Down Expand Up @@ -618,6 +619,14 @@ def set_video_fps(value: VideoFps) -> None:
set_setting(SettingKey.VIDEO_FPS_MAX, value)


def get_video_embed_artwork() -> bool:
return get_setting(SettingKey.VIDEO_EMBED_ARTWORK, False)


def set_video_embed_artwork(value: bool) -> None:
set_setting(SettingKey.VIDEO_EMBED_ARTWORK, value)


def get_background() -> bool:
return get_setting(SettingKey.BACKGROUND, True)

Expand Down
25 changes: 23 additions & 2 deletions src/usdb_syncer/song_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,7 @@ def _run_inner(self) -> UsdbSong:
_maybe_download_cover,
_maybe_download_background,
_maybe_write_audio_tags,
_maybe_write_video_tags,
):
self._check_flags()
job(ctx)
Expand Down Expand Up @@ -536,7 +537,7 @@ def _maybe_write_audio_tags(ctx: _Context) -> None:
try:
match path.suffix:
case ".m4a":
_write_m4a_tags(path, resource, ctx, options.embed_artwork)
_write_m4a_mp4_tags(path, resource, ctx, options.embed_artwork)
case ".mp3":
_write_mp3_tags(path, resource, ctx, options.embed_artwork)
case ".ogg":
Expand All @@ -560,7 +561,27 @@ def _maybe_write_audio_tags(ctx: _Context) -> None:
ctx.logger.debug(f"Audio tags written to file '{path}'.")


def _write_m4a_tags(
def _maybe_write_video_tags(ctx: _Context) -> None:
if not (options := ctx.options.video_options):
return
if not (path_resource := ctx.out.video.path_and_resource(ctx.locations, temp=True)):
return
path, resource = path_resource
try:
match path.suffix:
case ".mp4":
_write_m4a_mp4_tags(path, resource, ctx, options.embed_artwork)
case other:
ctx.logger.debug(f"Video tags not supported for suffix '{other}'.")
return
except Exception: # pylint: disable=broad-exception-caught
ctx.logger.debug(traceback.format_exc())
ctx.logger.error(f"Failed to write video tags to file '{path}'!")
else:
ctx.logger.debug(f"Video tags written to file '{path}'.")


def _write_m4a_mp4_tags(
path: Path, resource: str, ctx: _Context, embed_artwork: bool
) -> None:
tags = mutagen.mp4.MP4Tags()
Expand Down

0 comments on commit 5cfaa6d

Please sign in to comment.