From 2db84415bb784e5d4545350a7d33b4bfe08c4d7c Mon Sep 17 00:00:00 2001 From: Milan Date: Fri, 24 Mar 2023 22:57:15 +0100 Subject: [PATCH] config: add audio-upload-hooks Hooks can be used to automate the process of updating database columns when new audio files are uploaded. A hook command reads the path of an audio file and output a list of database columns to be updated with their respective values. Currently, the only supported database tables are calcms_events and calcms_audio_recordings. Some examples are included --- lib/calcms/series_events.pm | 32 ++++++-------- .../set-loudness-duration.pl | 29 +++++++++++++ tools/audio-upload-hooks/set-podcast-url.sh | 3 ++ tools/audio-upload-hooks/set-size.sh | 2 + website/agenda/config/config.cgi.off | 13 ++++++ website/agenda/planung/audio-recordings.cgi | 43 ++++++++++++++++++- 6 files changed, 102 insertions(+), 20 deletions(-) create mode 100755 tools/audio-upload-hooks/set-loudness-duration.pl create mode 100755 tools/audio-upload-hooks/set-podcast-url.sh create mode 100755 tools/audio-upload-hooks/set-size.sh diff --git a/lib/calcms/series_events.pm b/lib/calcms/series_events.pm index f493b39..686b2a3 100644 --- a/lib/calcms/series_events.pm +++ b/lib/calcms/series_events.pm @@ -22,15 +22,18 @@ use images(); # check permissions, insert and update events related to series -#use base 'Exporter'; -our @EXPORT_OK = qw( - check_permission - save_content - save_event_time - insert_event - delete_event - set_playout_status -); +sub get_content_columns($) { + my ($config) = @_; + return ( + 'series_name', 'title', 'excerpt', 'content', + 'html_content', 'user_title', 'user_excerpt', 'topic', + 'html_topic', 'episode', 'image', 'image_label', + 'series_image', 'series_image_label', 'podcast_url', 'archive_url', + 'live', 'published', 'playout', 'archived', + 'rerun', 'draft', 'disable_event_sync', 'modified_by', + 'content_format' + ); +} # update main fields of the event by id # do not check for project,studio,series @@ -65,16 +68,7 @@ sub save_content($$) { #TODO: double check series_name (needed for reassignment but not for editing...) my @keys = (); - for my $key ( - 'series_name', 'title', 'excerpt', 'content', - 'html_content', 'user_title', 'user_excerpt', 'topic', - 'html_topic', 'episode', 'image', 'image_label', - 'series_image', 'series_image_label', 'podcast_url', 'archive_url', - 'live', 'published', 'playout', 'archived', - 'rerun', 'draft', 'disable_event_sync', 'modified_by', - 'content_format' - ) - { + for my $key (get_content_columns($config)) { push @keys, $key if defined $entry->{$key}; } $entry->{rerun} = 0 unless $entry->{rerun}; diff --git a/tools/audio-upload-hooks/set-loudness-duration.pl b/tools/audio-upload-hooks/set-loudness-duration.pl new file mode 100755 index 0000000..769a2e5 --- /dev/null +++ b/tools/audio-upload-hooks/set-loudness-duration.pl @@ -0,0 +1,29 @@ +#!/usr/bin/perl +use warnings; +use strict; +use Symbol 'gensym'; +use IPC::Open3 qw(open3); +$| = 1; + +# measure duration and rms +# requires sox and libsox-fmt-all + +die unless $ARGV[0]; +my $pid + = open3(undef, undef, my $err = gensym(), "sox", $ARGV[0], "-n", "stats"); + +while (defined(my $line = <$err>)) { + my @fields = split /\s+/, $line; + if ($line =~ /^RMS lev dB/) { + print "calcms_audio_recordings.rmsLeft = " + . int($fields[3] + 0.5) . "\n"; + print "calcms_audio_recordings.rmsRight = " + . int($fields[4] + 0.5) . "\n"; + } elsif ($line =~ /^Length\ss/) { + print "calcms_audio_recordings.audioDuration = " + . int($fields[2] + 0.5) + . "\n"; + } +} +waitpid($pid, 0); +die if $?; diff --git a/tools/audio-upload-hooks/set-podcast-url.sh b/tools/audio-upload-hooks/set-podcast-url.sh new file mode 100755 index 0000000..323151f --- /dev/null +++ b/tools/audio-upload-hooks/set-podcast-url.sh @@ -0,0 +1,3 @@ +#!/bin/sh +echo "calcms_events.podcast_url = http://podcasts.org/files/$1" + diff --git a/tools/audio-upload-hooks/set-size.sh b/tools/audio-upload-hooks/set-size.sh new file mode 100755 index 0000000..ed8a7a2 --- /dev/null +++ b/tools/audio-upload-hooks/set-size.sh @@ -0,0 +1,2 @@ +#!/bin/sh +echo "calcms_audio_recordings.size = $(du -b $1 | cut -f1)" diff --git a/website/agenda/config/config.cgi.off b/website/agenda/config/config.cgi.off index 4fe18d4..d38e3ef 100755 --- a/website/agenda/config/config.cgi.off +++ b/website/agenda/config/config.cgi.off @@ -76,6 +76,19 @@ domain ${DOMAIN} theme default +# Hooks can be used to automate the process of updating database columns +# when new audio files are uploaded. +# A hook command +# reads the path of an audio file and +# output a list of database columns to be updated with their respective values. +# Currently, the only supported database tables are calcms_events and calcms_audio_recordings. + + + command1 ${BASE_DIR}/../tools/audio-upload-hooks/set-size.sh + command2 ${BASE_DIR}/../tools/audio-upload-hooks/set-loudness-duration.pl +# command3 ${BASE_DIR}/../tools/audio-upload-hooks/set-podcast-url.sh + + result_limit 500 diff --git a/website/agenda/planung/audio-recordings.cgi b/website/agenda/planung/audio-recordings.cgi index c1710ca..a908b63 100755 --- a/website/agenda/planung/audio-recordings.cgi +++ b/website/agenda/planung/audio-recordings.cgi @@ -21,6 +21,7 @@ use studios(); use series(); use template(); use audio_recordings(); +use series_events(); use events(); use audio(); use time(); @@ -434,14 +435,54 @@ sub updateDatabase { $entry->{rmsRight} = 0.0; $entry->{audioDuration} = 0.0; $entry->{modified_at} = time(); - $params->{id} = audio_recordings::insert( $config, $dbh, $entry ); + $entry->{id} = audio_recordings::insert( $config, $dbh, $entry ); + $params->{id} = $entry->{id}; } + call_hooks($config, $entry, $params); $config->{access}->{write} = 0; $params->{action_result} = 'done!'; return $params; } +sub call_hooks { + my ($config, $entry, $params) = @_; + print STDERR Dumper($config->{"audio-upload-hooks"}); + my $dbh = db::connect($config); + + $entry = audio_recordings::get( + $config, { + project_id => $entry->{project_id}, + studio_id => $entry->{studio_id}, + event_id => $entry->{event_id}, + path => $entry->{path} + } + )->[0] or die; + + for my $cmd (sort values %{$config->{"audio-upload-hooks"}}) { + my $audio_file = $config->{locations}->{local_audio_recordings_dir}.'/'.$entry->{path}; + open(my $fh, '-|', $cmd, $audio_file) or die "Failed to execute hook: $!"; + while (defined (my $line = (<$fh>))) { + if ($line =~ m/^calcms_audio_recordings\.([a-zA-Z0-9_-]+)\s*=\s*(\S+)/) { + my ($key, $value) = ($1, $2); + $entry->{$key} = $value; + die "invalid column $key for table calcms_audio_recordings" + unless exists audio_recordings::get_columns($config)->{$key}; + audio_recordings::update( $config, $dbh, $entry ); + } elsif ($line =~ m/^calcms_events\.([a-zA-Z0-9_-]+)\s*=\s*(\S+)/) { + my ($key, $value) = ($1, $2); + die "invalid column $key for calcms_events\n" + unless exists {map {$_=>1} series_events::get_content_columns($config)}->{$key}; + series_events::save_content($config, { + id => $entry->{event_id}, + $key => $value + }); + } + } + close $fh or die $!; + } +} + # return filename, filehandle and optionally error from upload sub getFilename { my $cgi = shift;