Home > Enterprise >  Converting ffmpeg loudnorm first pass dcf summary report output to data.frame R
Converting ffmpeg loudnorm first pass dcf summary report output to data.frame R

Time:12-21

Following from operations on a video with ffmpeg, a loudnorm first past report for purely audio files is produced

names(aud_proc_df)
[1] "in_files" "proc_out" "filter"

cmds_loudness_report <- with(aud_proc_df, sprintf("ffmpeg -hide_banner -i %s -af loudnorm=I=-23:TP=-2:LRA=7:print_format=summary -f null /dev/null 2>&1 | tail -n 12 >> loudness_rpt_all.txt", in_files)) # linux specific notation
lapply(cmds_loudness_report, system)

reading this as a .csv rather than .dcf

loudness_df_csv <- read.csv('loudness_rpt_all.txt', header = FALSE, sep =':')
head(loudness_df_csv)
                 V1                  V2
1  Input Integrated          -24.7 LUFS
2   Input True Peak           -1.6 dBTP
3         Input LRA             17.9 LU
4   Input Threshold          -37.8 LUFS
5 Output Integrated          -23.4 LUFS
6  Output True Peak           -2.0 dBTP
#data
structure(list(V1 = c("Input Integrated", "Input True Peak", 
"Input LRA", "Input Threshold", "Output Integrated", "Output True Peak", 
"Output LRA", "Output Threshold", "Normalization Type", "Target Offset", 
"Input Integrated", "Input True Peak", "Input LRA", "Input Threshold", 
"Output Integrated", "Output True Peak", "Output LRA", "Output Threshold", 
"Normalization Type", "Target Offset"), V2 = c("    -24.7 LUFS", 
"      -1.6 dBTP", "            17.9 LU", "     -37.8 LUFS", 
"   -23.4 LUFS", "     -2.0 dBTP", "           14.8 LU", "    -36.2 LUFS", 
"   Dynamic", "         0.4 LU", "    -23.9 LUFS", "       0.2 dBTP", 
"            22.0 LU", "     -37.6 LUFS", "   -23.6 LUFS", "     -2.0 dBTP", 
"           21.9 LU", "    -37.0 LUFS", "   Dynamic", "         0.6 LU"
)), row.names = c(NA, 20L), class = "data.frame")

then, for column notation portability between win and linux systems

df_names <- unique(loudness_df_csv$V1)
df_names2 <- gsub(' ', '_', df_names)

and then make a data.frame

loudnorm_rpt <- data.frame(loudness_df_csv$V2[which(loudness_df_csv$V1 == df_names[1])], loudness_df_csv$V2[which(loudness_df_csv$V1 == df_names[2])], loudness_df_csv$V2[which(loudness_df_csv$V1 == df_names[3])], loudness_df_csv$V2[which(loudness_df_csv$V1 == df_names[4])], loudness_df_csv$V2[which(loudness_df_csv$V1 == df_names[5])], loudness_df_csv$V2[which(loudness_df_csv$V1 == df_names[6])], loudness_df_csv$V2[which(loudness_df_csv$V1 == df_names[7])], loudness_df_csv$V2[which(loudness_df_csv$V1 == df_names[8])], loudness_df_csv$V2[which(loudness_df_csv$V1 == df_names[9])], loudness_df_csv$V2[which(loudness_df_csv$V1 == df_names[10])])
names(loudnorm_rpt) <- df_names2
rownames(loudnorm_rpt) <- c('A', 'B')

Should I just wrap this in a function or is there a dcf to data.frame function that I've missed?

CodePudding user response:

The dput was from the the read.csv output. Assuming the input to have key:value pairs

dat1 <- type.convert(as.data.frame(read.dcf(textConnection(paste(tapply(tmp, 
  cumsum(grepl(trimws(tmp[1], whitespace = ":.*"), tmp)), 
   FUN = \(x) paste(x, collapse = "\n")), collapse = "\n\n")))), as.is = TRUE)
 row.names(dat1) <- c("A", "B")

-output

> dat1
  Input Integrated Input True Peak Input LRA Input Threshold Output Integrated Output True Peak Output LRA Output Threshold
A       -24.7 LUFS       -1.6 dBTP   17.9 LU      -37.8 LUFS        -23.4 LUFS        -2.0 dBTP    14.8 LU       -36.2 LUFS
B       -23.9 LUFS        0.2 dBTP   22.0 LU      -37.6 LUFS        -23.6 LUFS        -2.0 dBTP    21.9 LU       -37.0 LUFS
  Normalization Type Target Offset
A            Dynamic        0.4 LU
B            Dynamic        0.6 LU

data

tmp <- c("Input Integrated:-24.7 LUFS", "Input True Peak:-1.6 dBTP", 
"Input LRA:17.9 LU", "Input Threshold:-37.8 LUFS", "Output Integrated:-23.4 LUFS", 
"Output True Peak:-2.0 dBTP", "Output LRA:14.8 LU", "Output Threshold:-36.2 LUFS", 
"Normalization Type:Dynamic", "Target Offset: 0.4 LU", "Input Integrated:-23.9 LUFS", 
"Input True Peak: 0.2 dBTP", "Input LRA:22.0 LU", "Input Threshold:-37.6 LUFS", 
"Output Integrated:-23.6 LUFS", "Output True Peak:-2.0 dBTP", 
"Output LRA:21.9 LU", "Output Threshold:-37.0 LUFS", "Normalization Type:Dynamic", 
"Target Offset: 0.6 LU")

CodePudding user response:

You could make a matrix out of V2 and use make.names.

f <- \(x) {
  x <- x[order(x$V1), ]
  `dimnames<-`(matrix(trimws(x$V2), 2), 
               list(c('A', 'B'), make.names(unique(x$V1)))) |>
    as.data.frame()
}

f(loudness_df_csv)
#   Input.Integrated Input.LRA Input.Threshold Input.True.Peak
# A       -24.7 LUFS   17.9 LU      -37.8 LUFS       -1.6 dBTP
# B       -23.9 LUFS   22.0 LU      -37.6 LUFS        0.2 dBTP
#   Normalization.Type Output.Integrated Output.LRA Output.Threshold
# A            Dynamic        -23.4 LUFS    14.8 LU       -36.2 LUFS
# B            Dynamic        -23.6 LUFS    21.9 LU       -37.0 LUFS
#   Output.True.Peak Target.Offset
# A        -2.0 dBTP        0.4 LU
# B        -2.0 dBTP        0.6 LU
  • Related