How to use the Linux arecord command to generate multiple FLAC files?

0

1

I would like to use the Linux arecord command to record and save multiple FLAC type files using the file time flag or similar:

--max-file-time 

For a wav file it is fairly straight forward to save multiple files using the --max-file-time flag. In the example below a new wav file is stored every 10 seconds of 6 channel audio:

arecord -t raw -f S16_LE -r 44100 --max-file-time 10 -D ac108 -c 6 --use-strftime listen-%H-%M-%v.wav

In this answer a contributor showed how to record to a FLAC file by piping the audio data to the flac program for output in flac formatfile, as demonstrated below:

arecord -t raw -f S16_LE -r 44100 -D ac108 -c 6 | flac - -f --endian little --sign signed --channels 6 --bps 16 --sample-rate 44100 -s -o listen.flac

My question is simply how to construct a Linux command that can record to multiple FLAC files where each file is similar in size?

user3430896

Posted 2019-04-18T12:39:27.140

Reputation: 23

Answers

0

Let's take advantage from these properties of raw format your arecord generates:

  • there is no header, no metadata;
  • each full sample is 6 (number of channels) times 2 bytes (i.e. 16 bits), so exactly 12 bytes;
  • there are exactly 44100 samples in each second.

So each second takes 44100 × 12 = 529200 bytes. To get 10 seconds you need 5292000 bytes. Note you cannot take a random chunk of 5292000 consecutive bytes from the stream, you need to make sure you don't start mid-sample. But the first 5292000 bytes will contain an integer number of samples for sure (strictly 44100 samples), then the next 5292000 bytes, then the next, and so on.

This is what split command can do: it can split the stream into pieces of a given size. The real magic comes from its --filter= option.

arecord -t raw -f S16_LE -r 44100 -D ac108 -c 6 \
| split -d -b 5292000 --filter='
flac - -f --endian little --sign signed --channels 6 --bps 16 --sample-rate 44100 -s -o "${FILE}.flac"
'

In the above pipeline split will run flac for each piece of data.

Notes:

  • --filter is not required by POSIX; your split may or may not support it.
  • See man 1 split to learn options that affect what ${FILE} expands to. I used just -d, so in my case it's x00, x01, x02, …
  • This is a pipeline, so Ctrl+C will send SIGINT to both arecord and split. In my tests this makes the last flac file truncated (split terminates flac in a hard way?), so I get ERROR while decoding data, state = FLAC__STREAM_DECODER_END_OF_STREAM while decoding the file later. Sending SIGINT to arecord only (e.g. killall arecord) allows split and (most importantly) flac to finish gracefully.
  • The command takes multiple lines for readability, but logically it's a one-liner in the following form:

    arecord … | split … --filter='flac …'
    

Kamil Maciorowski

Posted 2019-04-18T12:39:27.140

Reputation: 38 429

Thank you Kamil ! That is a beautiful solution. I tested it on my raspberry pi and so far no issue (unless I use Ctrl + C) to stop. The "killall arecord" cmd works great. I did not understand your comment "Note you cannot take a random chunk of 5292000 consecutive bytes from the stream, you need to make sure you don't start mid-sample." is this something I need to be concerned about? – user3430896 – 2019-05-03T19:46:22.483

While recording, using the above approach, occasionally I see the message "overrun!! (at least xxx ms long)". Does this mean the data was lost? – user3430896 – 2019-05-03T20:41:37.007

@user3430896 About a random chunk: if you choose to omit few bytes and then take 5292000 consecutive bytes, the chunk will not necessarily be aligned with boundaries of 12-bytes samples. flac doesn't know, doesn't care; it will encode the stream but the result may be distorted or just noise. Imagine a string abcdefg… you should decode as ab,cd,ef,… If you start with the offset of 1 character, you will get bc, de, fg, … – so completely different message. You don't need to be concerned: split starts with no offset for sure and each chunk contains 44100 samples. – Kamil Maciorowski – 2019-05-03T21:09:06.733

@user3430896 overrun!! is from arecord. It usually indicates the tool cannot output the result fast enough (e.g. memory card is too slow to store the output file in real time). In your case arecord pipes to split. split by itself is very fast but flac may not be fast enough. It's either CPU or storage device too slow to allow flac consume and process its chunk in real time. Data may accumulate in the pipe buffer but eventually arecord is told to pause streaming. At this moment it cannot record in real time, it must drop few samples. Yes, the data was lost. Reduce bandwidth. – Kamil Maciorowski – 2019-05-03T21:19:15.000

I tried recording over night at 16k/sec (rather than 44100) and it halted recording after around 7 hours with no final error message. There were around 14 overrun!! type messages. Each file was a 30 second recording size (-b 5760000). The arecord command was still running in the terminal many hours after recording stopped, so I killed it with the killall arecord command. I assume either the FLAC or split command died. – user3430896 – 2019-05-04T17:07:01.860

@user3430896 I'm sorry to hear that. I admit I have never tested the command running for so long. In theory it should work. I'm aware this statement doesn't help while you're experiencing issues in practice. At the moment I cannot diagnose the problem. It may be good to ask a separate question. The information you have given so far may not be enough to prevent it from being put on hold as "too broad", so make sure you quote all relevant messages and disclose details like OS, tool versions, filesystem and hardware you're writing to; even lines from dmesg if there's something related there. – Kamil Maciorowski – 2019-05-04T19:35:12.303

Thank you for your help. I'll dig deeper. – user3430896 – 2019-05-06T12:15:57.010