diff --git a/ffmpeg-patch/README b/ffmpeg-patch/README
index 8db02d7..8f41401 100644
--- a/ffmpeg-patch/README
+++ b/ffmpeg-patch/README
@@ -8,6 +8,14 @@ Car visiblement le patch ne s'applique plus :
sudo apt install yasm
+# Pour pouvoir gére les PNG en Debian Stable
+
+apt-get install zlib1g-dev
+
+# Pour pouvoir gérer la conversion en mp3
+
+ apt install libmp3lame-dev
+
git clone https://github.com/FFmpeg/FFmpeg.git
cd FFmpeg
@@ -22,6 +30,13 @@ Car visiblement le patch ne s'applique plus :
cd ..
- ./configure
+ ./configure --enable-libmp3lame
make
+
+
+# Et si ça ne fonctionne pas ?
+
+En cas de problème, peut-être cela vient-il des paramètres de ./configure. Tenter :
+
+./configure --enable-libmp3lame --enable-decoder=png --enable-encoder=png
diff --git a/podcasts/README b/podcasts/README
index 0557ace..9b8789e 100644
--- a/podcasts/README
+++ b/podcasts/README
@@ -74,8 +74,13 @@ drwxr-xr-x 5 root root 4096 janv. 16 11:53 lav-outils
]
}
-* Exécuter le script :
+* Exécuter le script sans génération des MP3 (qui prend du temps) le temps de vérifier que les timestamps de découpe des podcasts sont ok
+
root@raspberrypi:~/libreavous# lav-outils/podcasts/scripts/make-all-podcasts.pl --config lav-outils/podcasts/config/lav-20190115.json
+* Une fois que les timestamps de découpe des podcasts sont ok exécuter le script avec la génération des MP3
+
+root@raspberrypi:~/libreavous# lav-outils/podcasts/scripts/make-all-podcasts.pl --config lav-outils/podcasts/config/lav-20190115.json --mp3
+
* Les podcasts se retrouvent dans le dossier courant
diff --git a/podcasts/config/lav-20190528.json b/podcasts/config/lav-20190528.json
new file mode 100644
index 0000000..3ba43b1
--- /dev/null
+++ b/podcasts/config/lav-20190528.json
@@ -0,0 +1,31 @@
+{
+ "short_date" : "20190528",
+ "long_date" : "28 mai 2019",
+ "ffmpeg_bin" : "../FFmpeg/ffmpeg",
+ "chapters" : [
+ {
+ "start_timestamp" : "00:01:43.13",
+ "end_timestamp" : "00:15:17.24",
+ "short_chapter_name" : "chronique-in-code-we-trust-noemie-bergez-rgpd",
+ "chapter_title" : "Chronique « In code we trust » de Noémie Bergez : le RGPD"
+ },
+ {
+ "start_timestamp" : "00:17:39.69",
+ "end_timestamp" : "01:10:56.79",
+ "short_chapter_name" : "collectivites-et-logiciel-libre",
+ "chapter_title" : "Collectivités et logiciel libre"
+ },
+ {
+ "start_timestamp" : "01:16:07.13",
+ "end_timestamp" : "01:25:05.34",
+ "short_chapter_name" : "chronique-jouons-collectif-vincent-calame-dis-tu-ne-connaitrais-pas-un-logiciel-libre",
+ "chapter_title" : "Chronique « Jouons collectif » de Vincent Calame : « Dis, tu ne connaîtrais pas un logiciel libre ? »"
+ },
+ {
+ "start_timestamp" : "01:25:10.92",
+ "end_timestamp" : "01:26:49.16",
+ "short_chapter_name" : "annonces",
+ "chapter_title" : "Annonces"
+ }
+ ]
+}
diff --git a/podcasts/scripts/cleanindent b/podcasts/scripts/cleanindent
new file mode 100755
index 0000000..718b477
--- /dev/null
+++ b/podcasts/scripts/cleanindent
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+perltidy -b -bext='/' -t -et 4 -io make-all-podcasts.pl
diff --git a/podcasts/scripts/make-all-podcasts.pl b/podcasts/scripts/make-all-podcasts.pl
index 1858a1a..ae8a6e2 100755
--- a/podcasts/scripts/make-all-podcasts.pl
+++ b/podcasts/scripts/make-all-podcasts.pl
@@ -29,10 +29,14 @@ my ($help,$config,$verbose,$dryrun);
my $meta_data_script = "lav-outils/podcasts/scripts/make-metadata-image-podcast.sh";
my $verbose;
+my $mp3;
+my $textwebpage="
\n";
+
GetOptions ("help" => \$help,
- "config=s" => \$config,
- "verbose" => \$verbose,
- "dryrun" => \$dryrun);
+ "config=s" => \$config,
+ "mp3" => \$mp3,
+ "verbose" => \$verbose,
+ "dryrun" => \$dryrun);
if($help) {
usage();
@@ -47,22 +51,23 @@ sub usage {
Needs JSON perl library (apt install libjson-perl)
$0 --config conf_file.json
--config conf_file.json the configuration file containing stuff
+ --mp3 generate mp3 files
--help show this message
--verbose increase verbosity
--dryrun print commands without executing them
EOS
-;
+ ;
}
sub read_config {
my ($filename) = @_;
my $json_text = do { #read all the file in one shot
- open(my $json_fh, '<:encoding(UTF-8)', $filename)
- or die("Can't open \$filename\": $!\n");
+ open(my $json_fh, '<:encoding(UTF-8)', $filename)
+ or die("Can't open \$filename\": $!\n");
local $/;
- <$json_fh>
- };
+ <$json_fh>
+ };
my $json = JSON->new;
my $data = $json->decode($json_text);
@@ -71,14 +76,28 @@ sub read_config {
}
sub process {
- my ($config,$verbose,$dryrun)=@_;
+ my ($config,$mp3,$verbose,$dryrun)=@_;
my $data = read_config($config);
my $short_date = $data->{short_date};
+ my $year = substr $short_date,0,4;
my $long_date = $data->{long_date};
my $source_name = "libre-a-vous-$short_date";
my $title = "Libre à vous ! du $long_date sur Cause Commune";
my $ffmpeg_bin = $data->{ffmpeg_bin};
+
+ my $option_mp3_meta_data_script;
+ my @formats_files;
+
+ if($mp3) {
+ @formats_files = qw/ogg mp3/;
+ $option_mp3_meta_data_script = "yes";
+ }
+ else {
+ @formats_files = qw/ogg/;
+ $option_mp3_meta_data_script = "no";
+ }
+
for my $chapter (values @{$data->{chapters}}) {
my $start = $chapter->{start_timestamp};
my $end = $chapter->{end_timestamp};
@@ -100,13 +119,15 @@ sub process {
return 0;
}
}
-
+
# putting metadata
my $url = "https://media.april.org/audio/radio-cause-commune/libre-a-vous/emissions/$short_date/$source_name-$short_chapter_name.ogg";
- my $command = "$meta_data_script -s \"$source_name-$short_chapter_name.ogg\" -d \"output.ogg\" -u \"$url\" -t \"$title - Partie $chapter_title\" -p \"$ffmpeg_bin\"";
+ my $command = "$meta_data_script -s \"$source_name-$short_chapter_name.ogg\" -d \"output\" -u \"$url\" -t \"$title - Partie $chapter_title\" -p \"$ffmpeg_bin\" -y \"$year\" -m \"$option_mp3_meta_data_script\"";
+
if($dryrun) {
print "$command\n";
} else {
+
my @ret = `$command`;
if($?) {
print "Error while setting metadata in $short_chapter_name\n";
@@ -118,43 +139,70 @@ sub process {
}
}
- # renaming to target
- my $target_name = "$source_name-$short_chapter_name.ogg";
- my $command = "mv output.ogg $target_name";
+ # Update string for web site
+
+ my $command = "mediainfo --Inform=\"Audio;%Duration/String%\" output.ogg";
+
if($dryrun) {
print "$command\n";
} else {
my @ret = `$command`;
if($?) {
- print "Error while renaming $short_chapter_name\n";
+ print "Error while updating string for web site\n";
if($verbose) {
print Dumper @ret;
print Dumper $data;
}
return 0;
+ } else {
+ chomp($ret[0]);
+ $ret[0] =~ s/s/secondes/ig;
+ $ret[0] =~ s/min/minutes/ig;
+ my $url2 = $url =~ s/\.ogg/\.mp3/r;
+ $textwebpage = $textwebpage . "- $chapter_title (format OGG) (et format MP3) ($ret[0])
\n";
}
}
- # hashing
- my $command = "sha1sum $target_name > $target_name.sha1";
- if($dryrun) {
- print "$command\n";
- } else {
- my @ret = `$command`;
- if($?) {
- print "Error while hashing $target_name\n";
- if($verbose) {
- print Dumper @ret;
- print Dumper $data;
+ # renaming to target OGG and MP3
+ foreach my $format (@formats_files) {
+ my $target_name = "$source_name-$short_chapter_name.$format";
+ my $command = "mv output.$format $target_name";
+ if($dryrun) {
+ print "$command\n";
+ } else {
+ my @ret = `$command`;
+ if($?) {
+ print "Error while renaming $short_chapter_name.$format\n";
+ if($verbose) {
+ print Dumper @ret;
+ print Dumper $data;
+ }
+ return 0;
+ }
+ }
+
+ # hashing
+ my $command = "sha1sum $target_name > $target_name.sha1";
+ if($dryrun) {
+ print "$command\n";
+ } else {
+ my @ret = `$command`;
+ if($?) {
+ print "Error while hashing $target_name\n";
+ if($verbose) {
+ print Dumper @ret;
+ print Dumper $data;
+ }
+ return 0;
}
- return 0;
}
}
+
}
# putting metadata in main podcast
my $url = "https://media.april.org/audio/radio-cause-commune/libre-a-vous/emissions/$short_date/$source_name.ogg";
- my $command = "$meta_data_script -s \"$source_name.ogg\" -d \"output.ogg\" -u \"$url\" -t \"$title\" -p \"$ffmpeg_bin\"";
+ my $command = "$meta_data_script -s \"$source_name.ogg\" -d \"output\" -u \"$url\" -t \"$title\" -p \"$ffmpeg_bin\" -y \"$year\" -m \"$option_mp3_meta_data_script\"";
if($dryrun) {
print "$command\n";
} else {
@@ -169,37 +217,50 @@ sub process {
}
}
- # renaming to target
- my $command = "mv output.ogg $source_name.ogg";
- if($dryrun) {
- print "$command\n";
- } else {
- my @ret = `$command`;
- if($?) {
- print "Error while renaming $source_name\n";
- if($verbose) {
- print Dumper @ret;
- print Dumper $data;
+ # renaming to target OGG and MP3
+ foreach my $format (@formats_files) {
+
+ my $command = "mv output.$format $source_name.$format";
+ if($dryrun) {
+ print "$command\n";
+ } else {
+ my @ret = `$command`;
+ if($?) {
+ print "Error while renaming $source_name.$format\n";
+ if($verbose) {
+ print Dumper @ret;
+ print Dumper $data;
+ }
+ return 0;
+ }
+ }
+
+ # hashing
+ my $command = "sha1sum $source_name.$format > $source_name.$format.sha1";
+ if($dryrun) {
+ print "$command\n";
+ } else {
+ my @ret = `$command`;
+ if($?) {
+ print "Error while hashing $source_name.$format\n";
+ if($verbose) {
+ print Dumper @ret;
+ print Dumper $data;
+ }
+ return 0;
}
- return 0;
}
}
- # hashing
- my $command = "sha1sum $source_name.ogg > $source_name.ogg.sha1";
- if($dryrun) {
- print "$command\n";
- } else {
- my @ret = `$command`;
- if($?) {
- print "Error while hashing $source_name.ogg\n";
- if($verbose) {
- print Dumper @ret;
- print Dumper $data;
- }
- return 0;
- }
+ $textwebpage = $textwebpage . "
\n\n";
+
+ binmode(STDOUT, ":utf8");
+ print "\nText for the web page of the radio program :\n\n$textwebpage\n";
+
+ if(! $mp3) {
+ print "MP3 files not generated, please use --mp3 option to generate them\n";
}
+
}
-process($config,$verbose,$dryrun);
+process($config,$mp3,$verbose,$dryrun);
diff --git a/podcasts/scripts/make-metadata-image-podcast.sh b/podcasts/scripts/make-metadata-image-podcast.sh
index 22c7e96..053a662 100755
--- a/podcasts/scripts/make-metadata-image-podcast.sh
+++ b/podcasts/scripts/make-metadata-image-podcast.sh
@@ -1,6 +1,6 @@
#!/bin/bash
-
# Copyright (C) 2019 Quentin GIBEAUX
+# Copyright (C) 2019 Frédéric Couchet
#
# This file is part of lav-outils from "April/Libre à vous !"
#
@@ -17,51 +17,92 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-usage() { echo "$0 -s source_file -d destination_file -u http://... -t \"title\" -p path/to/ffmpeg/binary"; exit 0; }
+usage() { echo "$0 -s source_file -d destination_file -u http://... -t \"title\" -p path/to/ffmpeg/binary -y \"year\" -m \"yes or no\""; exit 0; }
+
[ $# -eq 0 ] && usage
-while getopts "s:d:u:t:p:h" arg; do
- case $arg in
- s)
- source=${OPTARG}
- ;;
- d)
- destination=${OPTARG}
- ;;
- u)
- url=${OPTARG}
- ;;
- t)
- title=${OPTARG}
- ;;
- p)
- FFmpegBin=${OPTARG}
- ;;
- h | *) # Display help.
- usage
- exit 0
- ;;
- esac
+
+while getopts "s:d:u:t:p:y:m:h" arg; do
+ case $arg in
+ s)
+ source=${OPTARG}
+ ;;
+ d)
+ destination=${OPTARG}
+ ;;
+ u)
+ url=${OPTARG}
+ ;;
+ t)
+ title=${OPTARG}
+ ;;
+ p)
+ FFmpegBin=${OPTARG}
+ ;;
+ y)
+ year=${OPTARG}
+ ;;
+ m)
+ mp3=${OPTARG}
+ ;;
+ h | *) # Display help.
+ usage
+ exit 0
+ ;;
+ esac
done
if [ ! -f $source ]; then
- echo "File $source does not exist"
- usage
- exit 1
+ echo "File $source does not exist"
+ usage
+ exit 1
fi
+
if [ ! -f "$FFmpegBin" ]; then
- echo "$FFmpegBin is not executable"
- usage
- exit 1
+ echo "$FFmpegBin is not executable"
+ usage
+ exit 1
fi
image="lav-outils/podcasts/images/image-pour-etiqueter-podcast.jpg"
-fichiertemp="$(command mktemp -t "tmp.XXXXXXXXXX.ogg")"
+
+fichiertempogg="$(command mktemp -t "tmp.XXXXXXXXXX.ogg")"
+fichiertempmp3="$(command mktemp -t "tmp.XXXXXXXXXX.mp3")"
+
+text=$(printf "Émission « Libre à vous ! » de l'April diffusée sur radio la « Cause Commune ».\n\nPour en savoir plus https://www.april.org/libre-a-vous et https://cause-commune.fm\n\nAdresse d'origine du fichier audio ${url}\n\nFichier diffusé selon les termes d’au moins une des licences suivantes : licence Art libre version 1.3 ou ultérieure http://artlibre.org/licence/lal/, licence Creative Commons By Sa version 2.0 ou ultérieure http://creativecommons.org/licenses/by-sa/2.0/fr/ et licence GNU FDL version 1.3 ou ultérieure http://www.gnu.org/licenses/fdl-1.3.html.")
(echo -en ";FFMETADATA1\nMETADATA_BLOCK_PICTURE=";(i=${image};t=3;m="image/jpeg";eval "w=`identify-im6 "$i"|awk '{g=$3;sub("x"," h=",g);print g;d=$5;gsub(/-.*/,"",d);print " d=" d}'`"; echo -en "\x00\x00\x00\x$(printf '%02x' $t)\x00\x00\x00\x$(printf '%02x' `echo -n "$m"|wc -c`)$m\x00\x00\x00\x00$(printf '%08x' $w|sed 's/../\\x&/g')$(printf '%08x' $h|sed 's/../\\x&/g')$(printf '%08x' $d|sed 's/../\\x&/g')\x00\x00\x00\xff$(printf '%08x' `stat -c '%s' "$i"`|sed 's/../\\x&/g')";cat "$i")|base64 --wrap=0) > i.meta
-${FFmpegBin} -y -i ${source} -acodec copy -map 0:0 -map_metadata -1 -metadata title="${title}" -metadata copyright="Diffusée selon les termes d’au moins une des licences suivantes : licence Art libre version 1.3 ou ultérieure http://artlibre.org/licence/lal/, licence Creative Commons By Sa version 2.0 ou ultérieure http://creativecommons.org/licenses/by-sa/2.0/fr/ et licence GNU FDL version 1.3 ou ultérieure http://www.gnu.org/licenses/fdl-1.3.html" -metadata artist="April - Cause Commune" -metadata contact="${url}" ${fichiertemp}
+# Generation du fichier OGG avec l'image de pochette (cover) et les métadonnées
+${FFmpegBin} -y -i ${source} -acodec copy -map 0:0 -map_metadata -1 -metadata title="${title}" -metadata license="Diffusée selon les termes d’au moins une des licences suivantes : licence Art libre version 1.3 ou ultérieure http://artlibre.org/licence/lal/, licence Creative Commons By Sa version 2.0 ou ultérieure http://creativecommons.org/licenses/by-sa/2.0/fr/ et licence GNU FDL version 1.3 ou ultérieure http://www.gnu.org/licenses/fdl-1.3.html Pour vérifier voir https://www.april.org/libre-a-vous" -metadata artist="April - Cause Commune" -metadata copyright="April - Cause Commune" -metadata genre="Podcast" -metadata contact="https://april.org/libre-a-vous" -metadata description="${text}" ${fichiertempogg}
-${FFmpegBin} -y -i ${fichiertemp} -i i.meta -acodec copy -map 0:0 -map_metadata 1 ${destination}
+${FFmpegBin} -y -i ${fichiertempogg} -i i.meta -acodec copy -map 0:0 -map_metadata 1 ${destination}.ogg
-rm ${fichiertemp}
+if [ "$mp3" = "yes" ]; then
+
+ # Generation du fichier MP3 avec conservation de l'image de pochette (cover), des métadonnées en deux passes
+
+ # Conservation de l'image de pochette (cover) et des métadonnées
+
+ ${FFmpegBin} -y -i ${destination}.ogg -map_metadata 0:s:0 ${fichiertempmp3}
+
+ # Passe pour avoir le champ Duration dans le fichier (qui n'est pas présent suite à la conversion de OGG en MP3)
+
+ ${FFmpegBin} -y -i ${fichiertempmp3} -acodec copy ${destination}.mp3
+
+ # Mise à jour des métadonnées pour tenir compte des métadonnées MP3
+
+ eyeD3 --user-text-frame="LICENSE:" ${destination}.mp3
+
+ eyeD3 --user-text-frame="comment:" ${destination}.mp3
+
+ eyeD3 -c "`echo "${text}"|sed '1,$s/.ogg/.mp3/'`" ${destination}.mp3
+
+ eyeD3 --user-text-frame="WOAF:`echo ${url%.ogg}.mp3`" ${destination}.mp3
+
+ eyeD3 --text-frame="TCOP:${year} April - Cause Commune Fichier diffusé selon les termes d’au moins une des licences suivantes : licence Art libre version 1.3 ou ultérieure http://artlibre.org/licence/lal/, licence Creative Commons By Sa version 2.0 ou ultérieure http://creativecommons.org/licenses/by-sa/2.0/fr/ et licence GNU FDL version 1.3 ou ultérieure http://www.gnu.org/licenses/fdl-1.3.html. Pour vérifier voir https://www.april.org/libre-a-vous" ${destination}.mp3
+
+fi
+
+rm ${fichiertempogg}
+rm ${fichiertempmp3}
rm i.meta