Git/suuid/: New commits
[sunny256-utils.git] / wav_to_opus
blob13282886dfbe1fbe8f5b30c472336af4e9b259dc
1 #!/usr/bin/env perl
3 #==============================================================================
4 # wav_to_opus
5 # File ID: a339248e-4e43-11e7-9f40-f74d993421b0
7 # [Description]
9 # Character set: UTF-8
10 # ©opyleft 2008– Øyvind A. Holm <sunny@sunbase.org>
11 # License: GNU General Public License version 2 or later, see end of file for
12 # legal stuff.
13 #==============================================================================
15 use strict;
16 use warnings;
17 use Getopt::Long;
19 local $| = 1;
21 my $EXIT_OK = 0;
22 my $EXIT_ERROR = 1;
24 our %Opt = (
26 'album' => "",
27 'bitrate' => "",
28 'description' => "",
29 'force' => 0,
30 'help' => 0,
31 'quiet' => 0,
32 'releasedate' => "",
33 'title' => "",
34 'tracknumber' => "",
35 'verbose' => 0,
36 'version' => 0,
40 my @opt_artists = ();
41 my @opt_comments = ();
42 my @opt_genres = ();
43 my @opt_performers = ();
45 our $progname = $0;
46 $progname =~ s/^.*\/(.*?)$/$1/;
47 our $VERSION = '0.9.0';
49 Getopt::Long::Configure('bundling');
50 GetOptions(
52 'album|a=s' => \$Opt{'album'},
53 'artist|A=s' => \@opt_artists,
54 'bitrate|b=s' => \$Opt{'bitrate'},
55 'comment|c=s' => \@opt_comments,
56 'description|d=s' => \$Opt{'description'},
57 'force|f' => \$Opt{'force'},
58 'genre|g=s' => \@opt_genres,
59 'help|h' => \$Opt{'help'},
60 'performer|p=s' => \@opt_performers,
61 'quiet|q+' => \$Opt{'quiet'},
62 'releasedate|r=s' => \$Opt{'releasedate'},
63 'title|t=s' => \$Opt{'title'},
64 'tracknumber|n=s' => \$Opt{'tracknumber'},
65 'verbose|v+' => \$Opt{'verbose'},
66 'version' => \$Opt{'version'},
68 ) || die("$progname: Option error. Use -h for help.\n");
70 $Opt{'verbose'} -= $Opt{'quiet'};
71 $Opt{'help'} && usage($EXIT_OK);
72 if ($Opt{'version'}) {
73 print_version();
74 exit($EXIT_OK);
77 exit(main());
79 sub main {
80 my $Retval = $EXIT_OK;
82 my $Lh = "[0-9a-fA-F]";
83 my $v1_templ = "$Lh\{8}-$Lh\{4}-1$Lh\{3}-$Lh\{4}-$Lh\{12}";
85 my $wav_file;
87 for my $curr (@opt_comments) {
88 if ($curr !~ /^\S+=/) {
89 warn("$progname: $curr: Invalid value in " .
90 "-c/--comment argument, must use the " .
91 "format \"x=y\".\n");
92 return $EXIT_ERROR;
96 for my $wav_file (@ARGV) {
97 if ($wav_file !~ /\.(wav|flac)$/i) {
98 warn("$progname: $wav_file: File name does not have " .
99 "a .wav or .flac extension\n");
100 return $EXIT_ERROR;
103 if (!-r $wav_file) {
104 warn("$progname: $wav_file: Cannot read file: $!\n");
105 return $EXIT_ERROR;
108 if (-d $wav_file) {
109 warn("$progname: $wav_file: Is a directory\n");
110 return $EXIT_ERROR;
113 my $out_file = $wav_file;
114 $out_file =~ s/^(.*)\.(wav|flac)$/$1.opus/i;
116 if (-e $out_file) {
117 if ($Opt{'force'}) {
118 if (!unlink($out_file)) {
119 warn("$progname: $out_file: " .
120 "Cannot delete file: $!\n");
121 return $EXIT_ERROR;
123 } else {
124 warn("$progname: $out_file: File already " .
125 "exists, use -f / --force " .
126 "to overwrite\n");
127 return $EXIT_ERROR;
131 my @Params = "opusenc";
133 length($Opt{'bitrate'}) &&
134 push(@Params, "--bitrate", $Opt{'bitrate'});
135 length($Opt{'album'}) &&
136 push(@Params, comment("ALBUM", $Opt{'album'}));
137 for my $curr (@opt_artists) {
138 push(@Params, comment("ARTIST", $curr));
140 length($Opt{'description'}) &&
141 push(@Params, comment("DESCRIPTION",
142 $Opt{'description'}));
143 for my $curr (@opt_performers) {
144 push(@Params, comment("PERFORMER", $curr));
146 for my $curr (@opt_genres) {
147 push(@Params, comment("GENRE", $curr));
149 length($Opt{'releasedate'}) &&
150 push(@Params, comment("RELEASEDATE",
151 $Opt{'releasedate'}));
152 length($Opt{'title'}) &&
153 push(@Params, comment("TITLE", $Opt{'title'}));
154 length($Opt{'tracknumber'}) &&
155 push(@Params, comment("TRACKNUMBER",
156 $Opt{'tracknumber'}));
157 for my $curr (@opt_comments) {
158 push(@Params, "--comment", $curr);
161 push(@Params, sprintf("%s", $wav_file));
162 push(@Params, $out_file);
164 my $suuid_cmd = "suuid -m -t encode -w eo " .
165 "-c \"$progname: @Params\"";
166 chomp(my $suuid_str = `$suuid_cmd`);
167 if (!defined($suuid_str) || $suuid_str !~ /^$v1_templ$/) {
168 warn("$progname: suuid error\n");
169 return $EXIT_ERROR;
172 push(@Params, "--comment", "ENC_ID=$suuid_str");
173 msg(1, join(" ", @Params));
174 system(@Params);
177 return $Retval;
180 sub comment {
181 my ($name, $val) = @_;
183 $name =~ tr/a-z/A-Z/;
184 return("--comment", "$name=$val");
187 sub print_version {
188 # Print program version
189 print("$progname $VERSION\n");
190 return;
193 sub usage {
194 # Send the help message to stdout
195 my $Retval = shift;
197 if ($Opt{'verbose'}) {
198 print("\n");
199 print_version();
201 print(<<"END");
203 Usage: $progname [options] wav_or_flac_file [...]
205 Convert .wav or .flac to .opus .
207 Options:
209 -a X, --album X
210 Name of music album.
211 -A X, --artist X
212 Name of artist/group. The option can be repeated if there are
213 several artists involved.
214 -b X, --bitrate X
215 Use X as encoding bitrate, kbit/sec.
216 -c X=Y, --comment X=Y
217 Add a custom metadata field, using the format "X=Y" where X is the
218 field name and Y the field value. The option can be repeated to add
219 several metadata entries.
220 -d X, --description X
221 A short text description of the contents.
222 -f, --force
223 Overwrite existing files.
224 -g X, --genre X
225 Music genre. The option can be repeated if the track can be
226 classified as several genres.
227 -h, --help
228 Show this help.
229 -n X, --tracknumber X
230 Track number of this song.
231 -p X, --performer X
232 The artist(s) who performed the work. In classical music this would
233 be the conductor, orchestra, soloists. In an audio book it would be
234 the actor who did the reading. In popular music this is typically
235 the same as the ARTIST and is omitted. The option can be repeated if
236 there are several performers.
237 -q, --quiet
238 Be more quiet. Can be repeated to increase silence.
239 -r X, --releasedate X
240 The date the album was released.
241 -t X, --title X
242 Title of song.
243 -v, --verbose
244 Increase level of verbosity. Can be repeated.
245 --version
246 Print version information.
249 exit($Retval);
252 sub msg {
253 # Print a status message to stderr based on verbosity level
254 my ($verbose_level, $Txt) = @_;
256 if ($Opt{'verbose'} >= $verbose_level) {
257 print(STDERR "$progname: $Txt\n");
259 return;
262 __END__
264 # This program is free software; you can redistribute it and/or modify it under
265 # the terms of the GNU General Public License as published by the Free Software
266 # Foundation; either version 2 of the License, or (at your option) any later
267 # version.
269 # This program is distributed in the hope that it will be useful, but WITHOUT
270 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
271 # FOR A PARTICULAR PURPOSE.
272 # See the GNU General Public License for more details.
274 # You should have received a copy of the GNU General Public License along with
275 # this program.
276 # If not, see L<http://www.gnu.org/licenses/>.
278 # vim: set ts=8 sw=8 sts=8 noet fo+=w tw=79 fenc=UTF-8 :