Split flac files using cue: shnsplit failed - audio

I use this command to split flac files using cue, and it worked for all files:
ffmpeg -i *.flac temp.wav
shnsplit -o flac -f *.cue -t "%n %t" temp.wav
mkdir bk; mv *.flac bk/
cuetag.sh *.cue *.flac
However, recently I encountered some files in a Touhou OST music collection, and shnsplit did not work:
shnsplit: error: m:ss.ff format can only be used with CD-quality files
ffprobe *.flac:
Output #0, wav, to 'Touhou Reiiden ~ Highly Responsive to Prayers.wav':
Metadata:
ISFT : Lavf58.38.101
Stream #0:0: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 48000 Hz, stereo, s16, 1536 kb/s
Metadata:
encoder : Lavc58.70.100 pcm_s16le
Cue:
REM GENRE Soundtrack
REM DATE 1996-11-xx
PERFORMER "太田順也(ZUN)"
TITLE "東方靈異伝 ~ Highly Responsive to Prayers"
REM REPLAYGAIN_ALBUM_GAIN -5.59 dB
REM REPLAYGAIN_ALBUM_PEAK 0.987305
FILE "Touhou Reiiden ~ Highly Responsive to Prayers.flac" FLAC
TRACK 01 AUDIO
TITLE "A Sacred Lot"
REM REPLAYGAIN_TRACK_GAIN -6.14 dB
REM REPLAYGAIN_TRACK_PEAK 0.985352
INDEX 01 00:00:00
TRACK 02 AUDIO
TITLE "永遠の巫女"
REM REPLAYGAIN_TRACK_GAIN -6.18 dB
REM REPLAYGAIN_TRACK_PEAK 0.987030
INDEX 01 03:08:29
TRACK 03 AUDIO
TITLE "陰陽 ~ The Positive and Negative"
REM REPLAYGAIN_TRACK_GAIN -6.35 dB
REM REPLAYGAIN_TRACK_PEAK 0.985962
INDEX 01 06:18:55
TRACK 04 AUDIO
TITLE "神へ捧げる魂 ~ Highly Responsive to Prayers"
REM REPLAYGAIN_TRACK_GAIN -3.59 dB
REM REPLAYGAIN_TRACK_PEAK 0.957123
INDEX 01 08:20:57
TRACK 05 AUDIO
TITLE "東方怪奇談"
REM REPLAYGAIN_TRACK_GAIN -4.25 dB
REM REPLAYGAIN_TRACK_PEAK 0.936157
INDEX 01 11:26:67
TRACK 06 AUDIO
TITLE "天使伝説"
REM REPLAYGAIN_TRACK_GAIN -3.57 dB
REM REPLAYGAIN_TRACK_PEAK 0.867889
INDEX 01 14:25:32
TRACK 07 AUDIO
TITLE "Oriental Magician"
REM REPLAYGAIN_TRACK_GAIN -6.00 dB
REM REPLAYGAIN_TRACK_PEAK 0.985138
INDEX 01 20:32:70
TRACK 08 AUDIO
TITLE "破邪の小太刀"
REM REPLAYGAIN_TRACK_GAIN -6.08 dB
REM REPLAYGAIN_TRACK_PEAK 0.942291
INDEX 01 24:13:05
TRACK 09 AUDIO
TITLE "魔鏡"
REM REPLAYGAIN_TRACK_GAIN -5.11 dB
REM REPLAYGAIN_TRACK_PEAK 0.862610
INDEX 01 26:22:38
TRACK 10 AUDIO
TITLE "the Legend of KAGE"
REM REPLAYGAIN_TRACK_GAIN -4.72 dB
REM REPLAYGAIN_TRACK_PEAK 0.987305
INDEX 01 29:52:38
TRACK 11 AUDIO
TITLE "いざ、倒れ逝くその時まで..."
REM REPLAYGAIN_TRACK_GAIN -8.28 dB
REM REPLAYGAIN_TRACK_PEAK 0.987183
INDEX 01 32:39:55
TRACK 12 AUDIO
TITLE "Civilization of Magic"
REM COMMENT "死なばもろとも"
REM REPLAYGAIN_TRACK_GAIN -2.69 dB
REM REPLAYGAIN_TRACK_PEAK 0.888946
INDEX 01 35:26:45
TRACK 13 AUDIO
TITLE "The 'Alice in Wonderland' Angel"
REM COMMENT "星幽剣士/星幽天使"
REM REPLAYGAIN_TRACK_GAIN -5.05 dB
REM REPLAYGAIN_TRACK_PEAK 0.965332
INDEX 01 39:28:34
TRACK 14 AUDIO
TITLE "アイリス"
REM REPLAYGAIN_TRACK_GAIN -0.62 dB
REM REPLAYGAIN_TRACK_PEAK 0.678742
INDEX 01 42:58:57
I found this solution online and it worked:
cuebreakpoints *.cue | sed s/\$/0/ | shnsplit -o flac *.wav
However, the output file name is just split-track[##].flac, and I need a more descriptive file name, i.e. the title of the piece.
Is there anyway to split the flac using cue that gives me individual flacs with its title as the filename?

I am answering to your last question, which is not related to the title of your post and the outputs you pasted.
How to give a custom name to shnsplit output files ?
As written in the man page, you can give a custom name pattern with option -t. There are several special strings that are recognized. For instance, to name files after track number and title: -t "%n-%t".
EDIT: sorry I missed the main difficulty. Here is another solution.
How to rename flac files after their tags ?
If you can’t use the -t argument, like in your case, you can still tag and rename the files afterwards.
First, apply tags to your files, based on the cuefile (I hope cuetag can successfully read your file, unlike shnsplit):
cuetag *.cue *.flac
Then, browse the files, read the tags, and rename them accordingly (as described in this post):
for a in *.flac; do
TITLE=`metaflac "$a" --show-tag=TITLE | sed s/.*=//g`
TRACKNUMBER=`metaflac "$a" --show-tag=TRACKNUMBER | sed s/.*=//g`
mv "$a" "`printf %02g $TRACKNUMBER`. $TITLE.flac";
done

Related

FFmpeg Concat audio giving extra milliseconds

Am Trying to concat 2 audio, i Want exact duration with millisecond accuracy.
my fist audio : audio1 = 17.2 seconds
my second audio : audio2 = 3.422 seconds
the concated audio should be 20.622 second but when i concat this audio ,
result audio duration is 20.698 second ,
how it's possible.
Concate command :-
ffmpeg -i processing1.m4a -i fileName_0_hi.m4a -filter_complex '[0:a][1:a]concat=n=2:v=0:a=1' output1.m4a
enter image description here
same issue with this command also :-
ffmpeg -f concat -i test.txt -c copy abc.m4a

Modify code so each snippets start from begin instead end

source : https://davidwalsh.name/video-preview#comment-515168
the part of code that trim videos into snippets :
# Loop and generate video snippets
mkdir $tempdir
interval=$(($length/$desiredsnippets-$starttimeseconds))
for i in $(seq 1 $desiredsnippets)
do
# Format the second marks into hh:mm:ss format
start=$(($(($i*$interval))+$starttimeseconds))
formattedstart=$(printf "%02d:%02d:%02d\n" $(($start/3600)) $(($start%3600/60)) $(($start%60)))
echo 'Generating preview part ' $i $formattedstart
# Generate the snippet at calculated time
ffmpeg -i $sourcefile -vf scale=$dimensions -preset fast -qmin 1 -qmax 1 -ss $formattedstart -t $snippetlengthinseconds -threads $(nproc) $tempdir/$i.mp4
done
`
Video length is 3600 (60mins)
Desired snippets = 30, that mean 2mins each
It always start at 0:02:00 to 0:04:00 -> and so on
but i want it start at 0:00:00 (1st snippet) -> 0:02:00 (2nd snippet) -> (this put in code because it said invalid code format)
I want to make it trim from start of each snippets instead end of each snippets.
This code trim video into multiple parts(snippets) that set by user, and then merged all snippets into one video.

Real-time monitoring of intermittent binary data

Context: monitor a low-volume, intermittent stream from a program
When debugging some program, one sometimes have to monitor some output. When output is ascii, no problem, just run in terminal (the program itself, or nc if it uses a TCP or UDP interface, or cat /dev/somedevice, or socat ..., whatever).
Need: monitor a binary stream real-time... and half-solutions
But sometimes output is binary. One can pipe it into various incantations of od, hd, e.g. od -t d1 for decimal numbers, od -t a1 for augmented ascii display (explicit non-printable characters using printable ones), etc.
The trouble is: those buffer the input until they have a complete line to print (a line often fitting 16 input characters). So basically until the program sends 16 character, the monitoring does not show anything. When the stream is low volume and/or intermittent, this defeats the purpose of a real-time monitoring. Many protocols indeed only send a handful of bytes at a time.
It would be nice to tell it "ok buffer the input if you wish, but don't wait more than delay x before printing it, even if it won't fill one line".
man od, man hd don't mention any related option.
Non-solution
Heavy programs like wireshark are not really an option: they cover only part of the needs and are not combinable. I often do things like this:
{ while read a ; do { echo -n -e 'something' ; } | tee >(od -t d1 >&2) ; done ; } | socat unix-connect:/somesocket stdio | od -t d1
This monitors the output, and each time I press enter in the terminal, injects the sequence "something". It works very well but terminal output is buffered by 16-byte chunks and thus delayed a lot.
Summary
How do you simply monitor binary output from a program without byte-alignment-dependent delay ?
I don't know which distribution you're using, but check to see whether you have, or can install, most. From the manpage:
OPTIONS
-b Binary mode. Use this switch when you want
to view files containing 8 bit characters.
most will display the file 16 bytes per line
in hexadecimal notation. A typical line
looks like:
01000000 40001575 9C23A020 4000168D ....#..u.#. #...
When used with the -v option, the same line
looks like:
^A^#^#^# #^#^U u 9C #A0 #^#^V8D ....#..u.#. #...
Not in the manpage, but essential for your task, is the keystroke F (N.B. upper-case), which puts most into 'tail mode'. In this mode, most updates whenever new input is present.
On the downside, most can't be told to begin in tail mode, so you can't just pipe to its stdin (it will try to read it all before showing anything). So you'll need to
<your_command> >/tmp/output
in the background, or in its own terminal, as appropriate. Then
most -b /tmp/output
and press F.
Here's the best thing I found so far, hope someone knows something better.
Use -w1 option in od, or one of the examples format strings in man hd that eats one byte at a time. Kind of works, though makes a column-based display, which does not use terminal area efficiently.
{ while read a ; do { echo -n -e 'something' ; } | tee >(od -t d1 >&2) ; done ; } | socat unix-connect:/somesocket stdio | hexdump -v -e '/1 "%_ad# "' -e '/1 " _%_u\_\n"'
This displays thing like this:
0# _nul_ (plenty of wasted space on the right... )
1# _1_ (no overview of what's happening...)
2# _R_
3# _ _
4# _+_
5# _D_
6# _w_
7# _d8_
8# _ht_
9# _nak_
The good thing is one can configure it to their context and taste:
{ while read a ; do { echo -n -e 'something' ; } | tee >(od -t d1 >&2) ; done ; } | socat unix-connect:/somesocket stdio | hexdump -v -e '/1 "%_ad# "' -e '/1 "%02X "' -e '/1 " _%_u\_\n"'
This displays thing like this:
0# 6B _k_
1# 21 _!_
2# F6 _f6_
3# 7D _}_
4# 07 _bel_
5# 07 _bel_
6# 60 _`_
7# CA _ca_
8# CC _cc_
9# AB _ab_
But still, a regular hd display would use screen area more efficiently:
hd
00000000 f2 76 5d 82 db b6 88 1b 43 bf dd ab 53 cb e9 19 |.v].....C...S...|
00000010 3b a8 12 01 3c 3b 7a 18 b1 c0 ef 76 ce 28 01 07 |;...<;z....v.(..|

removes bytes within file when binary string is found

so I'd like to remove parts within (NOT at beginning or the end, or I would have used dd) a binary file, when I encounter a certain binary string value. ie :
if FF FB FF FB A4 is found, remove 2048 bytes before the second FF FB here (meaning the first FF FB is deleted as well as the 2046 bytes preceeding it)
repeat till the end of the file.(no need to test/prevent "eating itself", range between that string occurences always much larger than 2048)
how can I do that in bash ?
thanks in advance
You can use grep to locate the "FF FB FF FB A4", then use dd to cut file:
pos=$(grep --only-matching --byte-offset --binary --text --perl-regexp "\xFF\xFB\xFF\xFB\xA4" filename|head -1|cut -d ':' -f1)
It will tell you where the string.
dd if=filename of=output bs=1 ibs=1 count=$pos
This get the leading part. I think you know how to deal with left staff

Bash filename prefix replacement

I've read around, but I can't seem to wrap my head around this. I'm converting ripped files I made in flac to mp3 for a mp3 player. This set is from two CDs though, so their number prefix is undesirable.
Some filename examples:
01 Foo 9.flac
02 Foo 10.flac
03 Foo 11.flac
04 Foo 12.flac
05 Foo 13.flac
25 Foo 1.flac
26 Foo 2.flac
...
Here's what I have so far
$for file in *Foo*.flac; do flac -cd "$file" | lame -q 0 -V0 - "/media/mp3player/speech/${file%.flac}.mp3"; done
How can I go about removing the number and space prefix, and ideally replace it with what corresponds to the ending number?
So step in the right direction would be
From: 25 Foo 1
To: Foo 1
But this would be ideal
From: 25 Foo 1
To: 1 Foo 1
I've read through the Shell Parameter Expansion section of the Bash Reference Manual, but without examples, I'm having a hard time. I'll keep tinkering, but I wanted to post to see if anyone had any insight.
There is probably a better version, but this should work:
for file in *Foo*.flac
do
n=${file#*Foo} # erase from filename Foo and preceding characters
n=${n%.flac} # get file index
fileout=${n}${file#[0-9]?}.mp3 #this works as long as you have two digits numbers only
flac -cd "$file" | lame -q 0 -V0 - "/media/mp3player/speech/${fileout}.mp3"
done
awk '{old=$0;a=$NF;gsub(".flac","",a);$1=a;new=$0;system("mv \""old"\" \""new"\"");}'
tested below:
> ls -1 01*
01 Foo 25.flac
01 Foo 26.flac
01 Foo 9.flac
> ls -1 01*| awk '{old=$0;a=$NF;gsub(".flac","",a);$1=a;new=$0;system("mv \""old"\" \""new"\"");}'
> ls -1 *.flac
25 Foo 25.flac
26 Foo 26.flac
9 Foo 9.flac
>

Resources