Wie nehmt ihr von jack auf? jack_rec; Skript

P

PySeq

|||||
Wie nehmt ihr von jack auf? Na ja, wahrscheinlich nutzt ihr größere Anwendungen (Qtractor, Ardour), die das mit drin haben.
Bei Ardour gefällt mir das Konzept nicht (Punkt "I thought this was free software " auf der Download-Seite).
Jedenfalls, es gibt da so ein winziges Tool "jack_rec", das bei jack dabei ist. Damit kann man schnell und einfach Audio von jack output-clients abgreifen. Nur die Syntax ist ein bißchen nervig (z.B. "jack_rec -f output.wav "qsynth:l_00" "qsynth:r_00" -b16 -d10000").
Ich hab' jetzt mal ein Perl-Skript drumherum geschrieben, so daß man auf der Konsole einen Output-Client, von dem man aufnehmen will, aus einer Liste auswählen kann. Hab' das Skript noch nicht in Gebrauch, aber es dürfte ganz praktisch sein.
Ausgabe erfolgt in Dateien "jack_01.wav", usw. im aktuellen Verzeichnis des Skripts:
Perl:
#!/usr/bin/perl

use warnings;
use strict;

use Cwd;

# jackrecord.pl
#
# Records from a selected jack audio ouptut client using 'jack_rec'.
#
# (C) 2019, PySeq. Licence: GNU GPL version 2.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.


sub getJackAudioOutputClients {
    my @a = `jack_lsp -p 2>/dev/null`;
    if (! @a) {
        print "\nError: Cannot connect to jack server. Maybe the jack server wasn't started.\n\n";
        exit 1;
    }
    my $i;
    my @b;
    for $i (0 .. $#a) {
        if ($a[$i] =~ m/properties:/ || $a[$i] =~ m/system:capture/) {
            next;
        }
        if ($a[$i + 1] =~ m/properties:/ && $a[$i + 1] =~ m/output/) {
            push(@b, $a[$i]);
        }
    }
    my %clients = ();
    my @c;
    for $i (@b) {
        chomp($i);
        @c = split(/\:/, $i);
        if (exists($clients{$c[0]})) {
            push($clients{$c[0]}, $c[1]);
        } else {
            $clients{$c[0]} = [$c[1]];
        }
    }
    return \%clients;
}

sub getChoice {
    my $headline = shift;
    my @choices = @{shift(@_)};
    my $default = shift;
    my $cls = shift;
    if ($#choices < 0 || $#choices > 9998) {
        die("List-length out of range (1-9999)");
    }
    if ($default < -1 || $default > $#choices) {
        die("Default-choice out of range");
    }
    if ($cls) {
        system("clear");
    }
    my $x = 0;
    print "\n$headline:\n\n";
    my $sprintfstr = int(log($#choices + 1) / log(10)) + 1;
    $sprintfstr = "%0" . $sprintfstr . "d";
    my $numberstring;
    for my $i (0 .. $#choices) {
        $numberstring = sprintf($sprintfstr, $i + 1);
        print "$numberstring. $choices[$i]\n";
    }   
    print "\n";
    my $inputstr = ""; 
    while ($x == 0) {
        print "Enter your choice";
        if ($default > -1) {
            print " (Default: \"" . ($default + 1) . ". $choices[$default]\")";
        }
        print ": ";
        $inputstr = <STDIN>;
        chomp($inputstr);
        if ($inputstr eq "") {
            if ($default > -1) {
                $inputstr = $default + 1;
                $x = 1;
            }
            else {
                next;
            }
        }
        if ($inputstr eq "q") {
            print "Bye.\n\n";
            exit 0;
        }
        if ($inputstr !~ /\D/ &&
            $inputstr >= 1 &&
            $inputstr <= $#choices + 1) {
            $x = 1;
        }
    }
    return $inputstr - 1;
}

sub getNum {
    my $thisdir = getcwd();
    my $num = 1;
    while (-e "$thisdir/out_" . sprintf("%02d", $num) . ".wav") {
        $num++;
    }
    return sprintf("%02d", $num);
}

my $clref = getJackAudioOutputClients();
my %clients = %{$clref};
my @client_keys = keys(%clients);
@client_keys = sort(@client_keys);
my $default = 0;
my $i;
for $i (0 .. $#client_keys) {
    if ($client_keys[$i] =~ m/^jack\_rack/) {
        $default = $i;
    }
}
my $choice_client = getChoice("Jack audio output to record from:", \@client_keys, $default, 1);

my $client_name = $client_keys[$choice_client];
my @client_values = @{$clients{$client_name}};

my $outfile = "jackout_" . getNum() .".wav";

my $choice_left = getChoice("Left channel to record from \"$client_name\":", \@client_values, 0, 0);

my $choice_right = getChoice("Right channel to record from \"$client_name\":", \@client_values, 0, 0);

my $record = "jack_rec -f ";
$record .= "$outfile ";
$record .= "\"$client_name:$client_values[$choice_left]\" ";
$record .= "\"$client_name:$client_values[$choice_right]\" ";
$record .= "-b16 -d10000";

print "\n$record\n";

print "Recording. Press Ctrl+c to stop.\n\n";
system($record);

Edit, 10.11.2019: Neue Version gepostet. Jetzt wird auch ausdrücklich nach dem linken und rechten Output, von dem aufgenommen werden soll, weil "jack_mixer" mehr als zwei solcher Outputs hat.
 
Zuletzt bearbeitet:
Respekt für Dein Skript. Für mich sehe ich den Use-case nicht so - ich benutze Ardour.

Ardours Vorgehen finde ich ehrlich gesagt nicht schlimm, es ist eben ein bisschen Druck da, für die Pakettierung was zu zahlen. Damit hält man die Leute fern, die nur einsacken wollen aber auf gar keinen Fall etwas geben. Und das Selbstkompilieren ist nicht schwer und der Code ist offen. Aus Interesse benutze ich gerade die Git-Version und bin schon relativ zufrieden mit der Stabilität. Ich mache aber auch nicht mehr als Multitrackaufnahmen. Ich wollte mal sehen, ob externe Tempowechsel schon bei der Aufnahme berücksichtigt werden (wäre cool für mein Setup mit hauptsächlich Hardware und wenn ich's richtig verstanden habe soll das in Version 6 dann möglich sein).

jack-timemachine hört sich wirklich praktisch an, wenn man etwas immer aufnahmebereit mitlaufen lassen möchte und beim Record-Drücken die letzten X Sekunden gleich dabeihaben möchte! Das habe ich mir mal installiert. Würde mich mal interessieren, warum es diese (künstliche?) Begrenzung auf 8 Kanäle gibt.
 


News

Zurück
Oben