Process selection with external command

Hi everyone,

I’d love to have a feature that basically replaces selected sound section with a result of external script.

This could make Audacity a really flexible tool, which could easily interact with complex pipelines of CLI programs (ffmpeg, sox, etc.) and apply any crazy experimental feature without losing productivity.

Detailed use case:

  • user selects a sound section and chooses Effect - External Command…
  • show a window with (editable) list of commands/scripts, where user selects a command
  • silently export current selection as a temporary wav file
  • run a shell script (which takes a path to the temporary file and expected output wav file as arguments or simply uses stdin/stdout instead)
  • remove currently selected sound from the track
  • insert output (that was produced by external command) on the track
  • remove temporary files

Is there any similar feature?

Is it possible to implement something similar with Macros/Chains, Nyquist, mod-script-pipe? Or writing a Module in C++ is the only way?

I found wxExecute was used in VST effects plugin registration code (which is unrelated) and also in export to an external program feature which is almost what I’m looking for.

Is wxExecute the only way Audacity currently runs external programs or there’s something else?

I also noticed that running the following command with mod-script-pipe

Export: Mode=Selection Filename="selection.wav" Channels=1

just opens an export dialog, instead of silently writing a wav file with a given Filename, which is probably unexpected.

Thank you!

Audacity has a built-in audio processing language called Nyquist.
Small scripts written in Nyquist can be conveniently applied to the selected audio using the Nyquist Prompt (Nyquist Prompt - Audacity Manual)
For more complex programming, Nyquist can run as a plug-in effect (Missing features - Audacity Support)

Nyquist can also read and write files.

Lots more information about Nyquist programming in the “See Also” section here: Missing features - Audacity Support

steve, thank you! So it turns out the whole problem can be solved with Nyquist. Could you move the topic to appropriate board please?

I’d love to see a clear minimal snippet example at some visible page of wiki, so those who are new to Audacity and Nyquist could easily google it and use as a template. I was expecting to find it with requests like “execute shell script from audacity”, “audacity selection apply shell script”, “call sox nyquist audacity” — results are pretty unrelated and confusing today.

Anyway, trying my best to approach the problem, I started with calling an external command. From XLISP manual it seems it’s possible with (system “touch /tmp/hello”) but it doesn’t work on UNIX. There’s even a solution on the same page. So I applied the solution and it worked but caused a crash:

mark (ptr=<optimized out>) at nyquist/xlisp/xldmem.c:392
392             while (!(this->n_flags & MARK))

So there’s probably a bug in the solution. As a workaround I replaced true with s_true and it worked fine.

What’s the reason of this code being published in the documentation instead of the code repository? Can we expect it will be merged to master someday? Such a necessary thing.

The other stuff is now pretty simple (deletion happens automatically):

(setq input-file "/var/tmp/input.wav")
(setq output-file "/var/tmp/output.wav")
(setq main-shell-script "/var/tmp/ffmpeg-atempo.sh")

(setq input-output-files (strcat input-file " " output-file))
(setq main-shell-command (strcat main-shell-script " " input-output-files))
(setq cleanup-shell-command (strcat "rm -f " input-output-files))

(system cleanup-shell-command)
(s-save s input-file)
(system main-shell-command)
(s-read output-file)

where ffmpeg-atempo.sh is

#!/bin/sh

INPUT="$1"
OUTPUT="$2"
ffmpeg -i "${INPUT}" -filter:a "atempo=2.0" -vn "${OUTPUT}"

Is there something like s-save which overwrites files? I tried

(s-overwrite s 1000000000 input-file)

and it fails with

Overwriting /var/tmp/input.wav at offset 0
error: bad argument type - NIL
Function: #<Subr-SND-OVERWRITE: #8407bcc0>
Arguments:
  S
  1000000000
  "/var/tmp/input.wav"
  NIL
  0
  0
  0
  0
  0

Or maybe we can remove files with Nyquist/XLISP?

Thank you!

Done.

Nyquist was developed by Professor Roger Dannenberg at CMU, and it is a stand-alone programming language. The home page for (stand-alone) Nyquist is: The Computer Music Project Software

Roger Dannenberg was also the mentor for Dominic Mazzoni, and the two of them are the co-founders of Audacity.

Quite early in the history of Audacity, the Nyquist library was shoe-horned into Audacity, with a simple “Nyquist Prompt” interface (the Nyquist Prompt has moved on since then, but is still present in Audacity Nyquist Prompt - Audacity Manual).

There are some differences between the standalone version of Nyquist, and Nyquist in Audacity. Some features have been stripped out for the Audacity version (various reasons), and additional, Audacity specific features have been added. Most of the “system” functions have been removed from the Audacity version, and some of the additional libraries have been removed.

Other than the Nyquist manual (Nyquist Reference Manual), much of the early documentation was written and/or collated by Edgar Franke, and resides on www.audacity-forum.de/

There is additional information, mostly focussed on Audacity aspects of Nyquist, in the Audacity manual and the Audacity wiki. The Audacity / Nyquist documentation is a work-in-progress (still much to do).

If you want to make full use of Nyquist’s system calls, then the standalone version of Nyquist would be better (see the Nyquist home page).

Nyquist’s audio processing functions are lower level than most of those in SoX, but are very powerful. SoX does have some benefits that are not available in Nyquist (particularly the broad range of audio formats supported by SoX, and superb quality resampling), but Nyquist is a full programming language and is extremely versatile for audio processing. Using Nyquist in Audacity has several advantages over the standalone version if you don’t need to use system calls to external applications.

So that means “system” function currently is not available in all OSes, not just UNIX (from source code it seems to be true) and we’ll never get it back? That’s pretty sad.

Was it some security issue? I didn’t find the answer from git and even older cvs repo, it turns out the functions were removed on the first revision.

Could we have a warning on some wiki page about this limitation, so new users won’t waste their time trying to use it?

Is there any alternative for average users (with typical binary distro, without patching/compiling skills) so they could run shell scripts per selection right from Audacity (besides LD_PRELOAD-like hack)?

Thank you!

I think it was, though the decision pre-dates my involvement with Audacity.

The “system” function is not listed in the Nyquist language reference, so I think it would be quite confusing to display a message saying that a command that is not listed in the Nyquist manual is not available in Audacity’s version of Nyquist.

Do you really need to use shell scripts? Are you wanting to do something that cannot be done with Nyquist?

Yes, I’d love to have such flexibility to be able to run any filtering code, written in any language (not even in shell or lisp or something else particular).

It doesn’t mean it can’t be done with Nyquist, it just means there are complex algorithms exist already, written in different languages. And they are tested and debugged. There’s no point to waste time on rewriting them in a different language and debug them, especially if you’re not into audio programming at all and just want to reuse best available solutions as quickly as possible.

I don’t even mean exactly stuff from ffmpeg or sox, just any algorithm from any program (just covered with some dumb CLI code), would be possible to run. Such feature would give kind of a superpower to Audacity :slight_smile:

Suppose it’s true, but we already have wxExecute in “Exporting to an External Program” — why is it still there then? :slight_smile: I’m not trying to troll, sorry if it feels so :slight_smile: We both don’t know the reason why the “system” function was removed, so why not consider adding it back (at least as some experimental feature, covered with #ifdef and disabled by default, until it’s verified to be safe and stable) and fix the issues it might causes?

Thank you!

One approach that should work now:

  1. Write a Nyquist plug-in to export the selection. A keyboard shortcut can be set for the plug-in, which could be triggered by Autokey or similar)
  2. Apply the CLI processing to the exported selection - again that could be done via Autokey or some other scripting/
  3. Write a Nyquist plug-in to read the file back into Audacity.

What you will soon be able to do (but not quite yet), is to use Audacity’s scripting API. This is not yet available without building Audacity (and “mod-script-pipe”) from the source code. Also. development of this feature is changing rapidly at the moment, but you can find some information in the alpha manual:
https://alphamanual.audacityteam.org/man/Scripting

I’ve already had almost the same amount of steps without even coding: with “Export Selected Audio - (external program)”, “Edit - Delete”, “Import - Audio…”. That’s exactly what kills productivity and flexibility.

Imagine a creative person in a flow state, who focuses on their audio editing things, and trying to use 20 effects or something. Some of them are just normal effects but some are “complex to use” effects.

They would need to distinguish them between each other and follow such unnatural steps, exactly for those effects which are “complex to use”. They would lose their creative state of mind every time they fail to do that.

Also distributing such solutions would be a disaster: it’s just hard and unnatural for average users to even configure such complex pipelines. Also setup instructions would differ for different OS users.

Thanks! I’ve already checked out mod-script-pipe. It’s pretty interesting project but still it would require some additional keyboard hotkeys binder.

Is there a plan to make the scripting API behave like a normal plugin: to appear in Effects menu, etc.? Automatically, without additional steps from user, like running that script from keys binding software or adding a script to autostart by OS. In order to make it possible such script should run from Audacity itself.

Thank you!

I believe there is a plan to have a second “Nyquist Prompt” type of effect, but one that can use Audacity’s macro commands from Nyquist. This doesn’t give you access to CLI effects, but it does give you access to arbitrary Audacity commands, including any type of plug-in that Audacity supports.

I don’t yet have more info than that.