FFmpeg check channels of a 7.1 audio for silence - audio

This is a follow-up question from my previous question asked here, where I needed to look for silence within a specific audio track. Here is the ffmpeg life-saver solution where helps to get some metadata:
ffmpeg -i file -map 0:a:1 -af astats -f null -
But I have other type of input .mp4 files where they have one single track of 8 (i.e. 7.1) audio channels. Apparently these files are transcoded from an original file (somehow the 4 track stereos are squished into these files). Now similar to my previous, I need to know if the original file was 2-channel stereo or 5.1 (6) channel.
How to know if a specific channel of an audio track (say Center channel) is silent/mute, possibly using ffmpeg? Here is a sample .mp4 file.

You can use the channelsplit filter to split the audio channels and run silencedetect on each.
Example:
ffmpeg -i test2.mp4 -filter_complex "[0:a]channelsplit=channel_layout=7.1:channels=FC[fc];[fc]silencedetect" -f null /dev/null
You can find more on audio channel manipulation here:
https://trac.ffmpeg.org/wiki/AudioChannelManipulation

There is also the astats filter which can be used to detect silent tracks/channels.
This i what it outputs for the channel 4 of the suggest test file, which appears indeed to be perfectly silent.
ffmpeg -i "$in" -vn -sn -dn -map 0:a -af "astats=measure_overall=none" -f null -
...
[Parsed_astats_0 # 0x6beed00] Channel: 4
[Parsed_astats_0 # 0x6beed00] DC offset: 0.000000
[Parsed_astats_0 # 0x6beed00] Min level: 0.000000
[Parsed_astats_0 # 0x6beed00] Max level: 0.000000
[Parsed_astats_0 # 0x6beed00] Min difference: 0.000000
[Parsed_astats_0 # 0x6beed00] Max difference: 0.000000
[Parsed_astats_0 # 0x6beed00] Mean difference: 0.000000
[Parsed_astats_0 # 0x6beed00] RMS difference: 0.000000
[Parsed_astats_0 # 0x6beed00] Peak level dB: -inf
[Parsed_astats_0 # 0x6beed00] RMS level dB: -inf
[Parsed_astats_0 # 0x6beed00] RMS peak dB: -inf
[Parsed_astats_0 # 0x6beed00] RMS trough dB: -inf
[Parsed_astats_0 # 0x6beed00] Crest factor: 1.000000
[Parsed_astats_0 # 0x6beed00] Flat factor: -inf
[Parsed_astats_0 # 0x6beed00] Peak count: 6057984
[Parsed_astats_0 # 0x6beed00] Bit depth: 0/0
[Parsed_astats_0 # 0x6beed00] Dynamic range: -inf
[Parsed_astats_0 # 0x6beed00] Zero crossings: 0
[Parsed_astats_0 # 0x6beed00] Zero crossings rate: 0.000000
[Parsed_astats_0 # 0x6beed00] Number of NaNs: 0
[Parsed_astats_0 # 0x6beed00] Number of Infs: 0
[Parsed_astats_0 # 0x6beed00] Number of denormals: 0
[Parsed_astats_0 # 0x6beed00] Channel: 5
...
Something like this would show an overview of all channels:
ffmpeg -i "$in" -vn -sn -dn -map 0:a -af "astats=measure_overall=none" -f null - 2>&1 \
| egrep 'Channel|(Max|Peak) level'
[Parsed_astats_0 # 0x7567d00] Channel: 1
[Parsed_astats_0 # 0x7567d00] Max level: 0.978271
[Parsed_astats_0 # 0x7567d00] Peak level dB: -0.190818
[Parsed_astats_0 # 0x7567d00] Channel: 2
[Parsed_astats_0 # 0x7567d00] Max level: 0.978271
[Parsed_astats_0 # 0x7567d00] Peak level dB: -0.190818
[Parsed_astats_0 # 0x7567d00] Channel: 3
[Parsed_astats_0 # 0x7567d00] Max level: 0.000006
[Parsed_astats_0 # 0x7567d00] Peak level dB: -103.162709
[Parsed_astats_0 # 0x7567d00] Channel: 4
[Parsed_astats_0 # 0x7567d00] Max level: 0.000000
[Parsed_astats_0 # 0x7567d00] Peak level dB: -inf
[Parsed_astats_0 # 0x7567d00] Channel: 5
[Parsed_astats_0 # 0x7567d00] Max level: 0.000006
[Parsed_astats_0 # 0x7567d00] Peak level dB: -103.162709
[Parsed_astats_0 # 0x7567d00] Channel: 6
[Parsed_astats_0 # 0x7567d00] Max level: 0.000006
[Parsed_astats_0 # 0x7567d00] Peak level dB: -103.162709
[Parsed_astats_0 # 0x7567d00] Channel: 7
[Parsed_astats_0 # 0x7567d00] Max level: 0.978271
[Parsed_astats_0 # 0x7567d00] Peak level dB: -0.190818
[Parsed_astats_0 # 0x7567d00] Channel: 8
[Parsed_astats_0 # 0x7567d00] Max level: 0.978271
[Parsed_astats_0 # 0x7567d00] Peak level dB: -0.190818

Related

How to get the sum of a value out of transactions over time

I have a df showing aprox. 1.600.000 transactions like:
start duration avg stop
1.457423e+09 1821.0 0.951126 1.457425e+09
1.457389e+09 35577.0 0.517104 1.457424e+09
1.457425e+09 1232.0 0.000000 1.457425e+09
1.457425e+09 333.0 1.100000 1.457425e+09
1.457425e+09 1.0 0.000000 1.457425e+09
Transaction can be overlapping. How can I I get the aggregated sum over time as shown in the lower graph in the picture using Python/Matplotlib

How to plot median value on boxplot?

I have this boxplot but it is hard to read what value the value of the green line. How can I plot that value? Or is there another way?
One thing you can do could be just plotting directly from the medians calculated from the dataframe
In [204]: df
Out[204]:
a b c d
0 0.807540 0.719843 0.291329 0.928670
1 0.449082 0.000000 0.575919 0.299698
2 0.703734 0.626004 0.582303 0.243273
3 0.363013 0.539557 0.000000 0.743613
4 0.185610 0.526161 0.795284 0.929223
5 0.000000 0.323683 0.966577 0.259640
6 0.000000 0.386281 0.000000 0.000000
7 0.500604 0.131910 0.413131 0.936908
8 0.992779 0.672049 0.108021 0.558684
9 0.797385 0.199847 0.329550 0.605690
In [205]: df.boxplot()
Out[205]: <matplotlib.axes._subplots.AxesSubplot at 0x103404d6a0>
In [206]: for s, x, y in zip(df.median().map('{:0.2f}'.format), np.arange(df.shape[0]) + 1, df.median()):
...: plt.text(x, y, s, va='center', ha='center')

How to categorize positive and negative features from top features

I have trained user reviews thru average tfidf wor2vec model and got top features. Would like to tag top features as positive & negative.
Could you please suggest.
def top_tfidf_feats(row, features, top_n=1):
''' Get top n tfidf values in row and return them with their corresponding feature names.'''
topn_ids = np.argsort(row)[::-1][:top_n]
top_feats = [(features[i], row[i]) for i in topn_ids]
df = pd.DataFrame(top_feats)
df.columns = ['feature', 'tfidf']
return df
top_tfidf = top_tfidf_feats(final_tf_idf[1,:].toarray()[0],tfidf_feat,10)
Top 10 features...
feature tfidf
------- ------
0 urgent 0.513783
1 tells 0.501945
2 says 0.490708
3 clear 0.424756
4 care 0.206723
5 not 0.141886
6 flanum 0.000000
7 flap 0.000000
8 flare 0.000000
9 flared 0.000000
10 flares 0.000000

Getting exponential values when using describe() in Python

I am getting exponential output when i use the below describe function:
error_df = pandas.DataFrame({'reconstruction_error': mse,'true_class':
dummy_y_test_o})
print(error_df)
error_df.describe()
I tried printing the values in error_df and the count is 3150. But why do i get a exponential value then?
reconstruction_error true_class
0 0.000003 0
1 0.000003 1
... ... ...
3148 0.000003 2
3149 0.000003 0
[3150 rows x 2 columns]
Out[17]:
reconstruction_error true_class
count 3.150000e+03 3150.000000
mean 3.199467e-06 1.000000
std 1.764693e-07 0.816626
min 2.914150e-06 0.000000
25% 3.058539e-06 0.000000
50% 3.092931e-06 1.000000
75% 3.423379e-06 2.000000
max 3.737767e-06 2.000000

How to check a condition and then print specific fields in lines before the line with the condition using awk?

I have a file with the following output:
58.752391 0.000 1 1 6.152565 2.757839 14.558406 0.000000 2.156979 0.000000 0.000000 0 0 0 1
16.089417316313 0.000000000000 6.171292860915 2.757949885550 -150168 0
6.953218e-310 0.000000e+00 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
0.000000 0.000000 0 0 0 0 0.000000 0.000000 0.000000 0
0.000000 0.000000 0 0 0 0 0.000000 0.000000 0.000000 0
-1.000000 -1.000000
0
14034.172996 0.000 13 13 1.107936 1.107936 -1.000000 -1.000000 -1.000000 23.670258 34.172995 0 0 0 0
3085.963203076240 0.667625281751 10.905159250868 8.915904022910 -150168 639
6.953218e-310 0.000000e+00 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
3.120454 8.844320 8 1 127.895 0 23.670258 1.107936 0.000000 0
1.107936 8.390152 13 5 1e+50 0 34.172995 1.107936 0.000000 0
-1.000000 -1.000000
3 CE1(5-1;8-1) SN1 SN2
and so on...
I would like to check whether the two numbers in the 6th line (and then every 8th line) are different than -1.000000. If so, depending on which (the first, second or both) one is different, I'd like to produce the following output:
1) The first number is different than -1.000000:
this different number, 4 lines before this number - the third column (in this example 6.171292860915 if the number was different than -1.000000), 2 lines before this number - 8th column (in this example 0.000000), the same line - 7th column, the line after this number
2) The second number is different than -1.000000:
this different number, 4 lines before this number - the fourth column, 1 line before this number - 8th column, the same line - 7th column, the line after this number
3) The first and second number are different than -1.000000:
Output from 1)
Output from 2)
I know how to use sed to extract these lines where -1.000000 in my example are. Now I think I should include some awk's ifs in my sed command to check whether the line contains -1.000000 or other numbers and then print what I need. I have no idea, however, how to refer to lines before that which is being examined by sed. I'd be grateful for any help or clues. Thank you!
Perl to the rescue:
#!/usr/bin/perl
use warnings;
use strict;
# Read in "paragraph mode".
$/ = q();
# Auto add newlines.
$\ = "\n";
while (<>) {
my #lines = map [ split ], split /\n/; # Create an array of arrays.
if (-1 != $lines[5][0]) {
print join ' ', $lines[5][0], $lines[1][2], $lines[3][7],
$lines[3][6], #{ $lines[6] };
}
if (-1 != $lines[5][1]) {
print join ' ', $lines[5][1], $lines[1][3], $lines[4][7],
$lines[4][6], #{ $lines[6] };
}
}
In awk, the variable NR holds the line number, so the expression
NR % 8 == 6 { ..... }
will select lines 6, 14, 22 and so on. You only need a counter, but variables are automatically initialized to zero, so you get the sequence number (1 for line 6, 2 for line 14 and so on) with an expression like this
++seqno
Hope that helps....
one more solution in awk
awk '{if(NR%8==2){a=$3;b=$4};if(NR%8==4){a=$8","$7","a};if(NR%8==5){b=$8","$7","b};if(NR%8==6){c=$1;d=$2};if(NR%8==7){if(c!=-1.000000)print a,$0;if(d!=-1.000000)print b,$0 }}' inputfilename
if I break the above command as below
awk '{
if(NR%8==2){a=$3;b=$4};
if(NR%8==4){a=$8","$7","a};
if(NR%8==5){b=$8","$7","b};
if(NR%8==6){c=$1;d=$2};
if(NR%8==7){
if(c!=-1.000000)print a,$0;
if(d!=-1.000000)print b,$0
}
}' inputfilename
I am storing the output details in a and b from the beginning while reading file line by line like NR%8==2 is line 2 , NR%8==4 is line 4 of file and so on. At the 7th line (NR%8==7), I am checking for values c and d stored from line 6 (NR%8==6), if c and d has mismatch values we will print the output with 7th line content.

Resources