mkb79 / audible-cli

A command line interface for audible package. With the cli you can download your Audible books, cover, chapter files.
GNU Affero General Public License v3.0
423 stars 45 forks source link

decrypt: ffmpeg needs special characters in input filename escaped #199

Closed philgoetz closed 3 months ago

philgoetz commented 3 months ago

[ADDED: You can skip all of this comment and just read the next one, which explains what the problem is.]

I was running

audible decrypt --all -d ../decrypted/

and it crashed while decrypting the 88th file:

File decryption successful: ../decrypted/Connecting_with_the_Autism_Spectrum_How_to_Talk_How_to_Listen_and_Why_You_Shouldnt_Call_it_High-Functioning-AAX_22_32.m4b Uncaught Exception Traceback (most recent call last): File "/usr/local/lib/python3.9/site-packages/audible_cli/cli.py", line 65, in main sys.exit(cli(*args, kwargs)) File "/usr/local/lib/python3.9/site-packages/click/core.py", line 1157, in call return self.main(args, kwargs) File "/usr/local/lib/python3.9/site-packages/click/core.py", line 1078, in main rv = self.invoke(ctx) File "/usr/local/lib/python3.9/site-packages/click/core.py", line 1688, in invoke return _process_result(sub_ctx.command.invoke(sub_ctx)) File "/usr/local/lib/python3.9/site-packages/click/core.py", line 1434, in invoke return ctx.invoke(self.callback, ctx.params) File "/usr/local/lib/python3.9/site-packages/click/core.py", line 783, in invoke return __callback(args, kwargs) File "/usr/local/lib/python3.9/site-packages/click/decorators.py", line 92, in new_func return ctx.invoke(f, obj, *args, *kwargs) File "/usr/local/lib/python3.9/site-packages/click/core.py", line 783, in invoke return __callback(args, *kwargs) File "/cygdrive/d/data/audio_/Audible/audible-cli/plugins/cmddecrypt0.py", line 602, in cli decrypter.run() File "/cygdrive/d/data/audio/Audible/audible-cli/plugins/cmd_decrypt0.py", line 488, in run subprocess.check_output(base_cmd, text=True) # noqa: S603 File "/usr/lib/python3.9/subprocess.py", line 424, in check_output return run(popenargs, stdout=PIPE, timeout=timeout, check=True, File "/usr/lib/python3.9/subprocess.py", line 528, in run raise CalledProcessError(retcode, process.args, subprocess.CalledProcessError: Command '['ffmpeg', '-v', 'quiet', '-stats', '-audible_key', '548be09d55d86390e49020612d83753a', '-audible_iv', 'e9f7909df7797fae5321dbbf48644290', '-i', "'Consciousness_Confessions_of_a_RomanticReductionist(MIT_Press)-AAX_22_32.aaxc'", '-c', 'copy', "'../decrypted/Consciousness_Confessions_of_a_RomanticReductionist(MIT_Press)-AAX_22_32.m4b'"]' returned non-zero exit status 1.

However, when I constructed the same ffmpeg call and ran it from the command line, it succeeded:

$ ffmpeg -v quiet -stats -audible_key 548be09d55d86390e49020612d83753a -audible_iv e9f7909df7797fae5321dbbf48644290 -i "Consciousness_Confessions_of_a_RomanticReductionist(MIT_Press)-AAX_22_32.aaxc" -c copy "../decrypted/Consciousness_Confessions_of_a_RomanticReductionist(MIT_Press)-AAX_22_32.m4b" frame= 1 fps=0.0 q=-1.0 size= 0kB time=00:00:00.00 bitrate=256727.3kbits/ frame= 1 fps=0.0 q=-1.0 size= 21760kB time=01:37:08.67 bitrate= 30.6kbits/s frame= 1 fps=1.0 q=-1.0 size= 37376kB time=02:46:58.38 bitrate= 30.6kbits/s frame= 1 fps=0.7 q=-1.0 size= 49152kB time=03:38:59.89 bitrate= 30.6kbits/s frame= 1 fps=0.5 q=-1.0 size= 59136kB time=04:23:18.20 bitrate= 30.7kbits/s frame= 1 fps=0.4 q=-1.0 size= 68864kB time=05:05:29.22 bitrate= 30.8kbits/s frame= 1 fps=0.3 q=-1.0 size= 77568kB time=05:44:56.31 bitrate= 30.7kbits/s frame= 1 fps=0.3 q=-1.0 size= 85760kB time=06:21:23.82 bitrate= 30.7kbits/s frame= 1 fps=0.2 q=-1.0 size= 93440kB time=06:54:41.11 bitrate= 30.8kbits/s frame= 1 fps=0.2 q=-1.0 Lsize= 97910kB time=07:04:17.56 bitrate= 31.5kbits/s speed=6.08e+03x

And when I re-ran

audible decrypt --all -d ../decrypted/

it successfully decrypted that same file. [ADDED: Hmm, probably not. Probably the output file already existed, and it skipped it.]

philgoetz commented 3 months ago

The problem is the parentheses in the filename. The input filename is passed to ffmpeg inside double-quotes. It needs each parentheses within the double-quotes escaped. That is, decrypt calls something like

ffmpeg -i "foo(bar)"

when it needs

ffmpeg -i "foo\(bar\)"

Probably the same thing will happen if the name contains [, *, or other characters interpreted as part of a regexp.

devnoname120 commented 3 months ago

@philgoetz The problem is the opposite, the filename is escaped even though it's passed to ffmpeg directly.

It errors out because audible-cli passes this non-existent path: 'Consciousness_Confessions_of_a_Romantic_Reductionist(MIT_Press)-AAX_22_32.aaxc'

Instead it should pass: Consciousness_Confessions_of_a_Romantic_Reductionist(MIT_Press)-AAX_22_32.aaxc

See https://github.com/mkb79/audible-cli/pull/202 for a fix.

mkb79 commented 3 months ago

@devnoname120 Have you verified your solution with folder or file names which contains whitespaces?!

devnoname120 commented 3 months ago

@mkb79 I didn't see a reason why it wouldn't work, but I just tried and I confirm that it works fine.

❯ ls -lFh
Alias tip: l
Permissions User Group  Size       Date Modified                                              Name
.rw-r--r--  root root  438 MB Sun Apr  7 09:32:19 2024  A Redacted Book Name (that contains parentheses)(Some Editor)-AAX_44_128.aaxc
.rw-r--r--  root root   18 KB Sun Apr  7 09:32:02 2024  A Redacted Book Name (that contains parentheses)(Some Editor)_(500).jpg
.rw-r--r--  root root  5.9 KB Sun Apr  7 09:32:02 2024  A Redacted Book Name (that contains parentheses)(Some Editor)-chapters.json
.rw-r--r--  root root  2.5 KB Sun Apr  7 09:32:02 2024  A Redacted Book Name (that contains parentheses)(Some Editor)-AAX_44_128.voucher

❯ audible --verbosity DEBUG --profile de decrypt --all --rebuild-chapters --force-rebuild-chapters
debug: Audible-cli version: 0.3.1
debug: App dir: /root/.audible
debug: Plugin dir: /root/dev/audible-cli/plugin_cmds
debug: Config loaded from config.toml
debug: Auth file de.json for profile de loaded.
size=       3kB time=-577014:32:22.77 bitrate=N/A speed=N/A
Using chapters from /tmp/tmp.uhgH4qSdKf/folder with spaces/A Redacted Book Name (that contains parentheses)(Some Editor)-chapters.json
Found 18 chapters to prepare.
frame=    1 fps=0.1 q=-1.0 Lsize=  441863kB time=07:55:07.11 bitrate= 127.0kbits/s speed=2.27e+03x
File decryption successful: /tmp/tmp.uhgH4qSdKf/folder with spaces/A Redacted Book Name (that contains parentheses)(Some Editor)-AAX_44_128.m4b
mkb79 commented 3 months ago

@devnoname120 I had some issues with the Windows shell and whitespaces in the past. But I don’t have a Windows machine anymore, so I can’t test this.

philgoetz commented 3 months ago

(this reply is @devnoname120)

@mkb79 I didn't see a reason why it wouldn't work, but I just tried and I confirm that it works fine.

Where is the fix you speak of? It isn't here, and it isn't in #202 either.

devnoname120 commented 3 months ago

@philgoetz

it isn't in https://github.com/mkb79/audible-cli/pull/202 either.

?

devnoname120 commented 3 months ago

@mkb79 I spinned up a Windows 11 virtual machine and I tested both using cmd.exe and PowerShell.exe.

I confirm that it didn't work without my changes, and it now works after applying my changes.

Before:

image image

After:

SCR-20240408-sdwn SCR-20240408-sgcw
mkb79 commented 3 months ago

@devnoname120 Thank you for your work and time. I'll merge your pr now.