C.Astraea
C.Astraea

Reputation: 185

Passing key and values to external command from jq

What I'm trying to do:

Use jq to pass along parameters to ffmpeg in a bash script. Have a JSON in this external file that I generate regularly.

{
   "streams":[
      {
         "track":"/var/www/html/stream1.m3u8",
         "link":"http://playertest.longtailvideo.com/adaptive/bipbop/bipbop.m3u8"
      },
      {
         "track":"/var/www/html/stream2.m3u8",
         "link":"https://mnmedias.api.telequebec.tv/m3u8/29880.m3u8"
      },
      {
         "track":"/var/www/html/stream3.m3u8",
         "link":"http://www.streambox.fr/playlists/test_001/stream.m3u8"
      }
   ]
}

This is the command I've tried based on the response found here https://github.com/stedolan/jq/issues/503

jq -r '.streams[] | ffmpeg -v verbose -i  \(.link | @sh) -c copy -flags -global_header -hls_time 10 -hls_list_size 6 -hls_wrap 10 -start_number 1 \(.Track | @sh)"' streams.json | sh

However I get this error message:

jq: error: syntax error, unexpected IDENT, expecting $end (Unix shell quoting issues?) at <top-level>, line 1:
.streams[] | ffmpeg -v verbose -i  \(.link | @sh) -c copy -flags -global_header -hls_time 10 -hls_list_size 6 -hls_wrap 10 -start_number 1 \(.Track | @sh)"                       
jq: 1 compile error

Upvotes: 2

Views: 2908

Answers (3)

Charles Duffy
Charles Duffy

Reputation: 295403

The shortest possible change to your original code is just to add the quotes that were missing:

jq -r '.streams[] | "ffmpeg -v verbose -i  \(.link | @sh) -c copy -flags -global_header -hls_time 10 -hls_list_size 6 -hls_wrap 10 -start_number 1 \(.Track | @sh)"' streams.json | sh
#                   ^-- this was missing

Note that "ffmpeg ..." is a string, and is contained in quotes. That said, you're relying on jq to generate safe code for your shell -- since it has features explicitly built for the purpose, this isn't as bad as an idea as it might be otherwise; but it's still better practice to avoid code generation wherever possible.


As an alternate approach that avoids code generation and is safe with all possible filenames, use jq to generate a NUL-delimited stream of track / link pairs, and a BashFAQ #1 loop to iterate over them:

#!/usr/bin/env bash

while IFS= read -r -d '' track && IFS= read -r -d '' link; do
  ffmpeg -v verbose -i "$link" -c copy -flags -global_header -hls_time 10 \
         -hls_list_size 6 -hls_wrap 10 -start_number 1 "$track" 
done < <(jq -j '.streams[] | ( .track + "\u0000" + .link + "\u0000" )' streams.json) 

Upvotes: 3

Gilles Qu&#233;not
Gilles Qu&#233;not

Reputation: 185105

Using to generate the commands :

(replace file.json with your own path/file)

#!/bin/bash

node<<EOF
var j=$(<file.json);
for (var i = 0; i<j.streams.length; i++) {
   console.log("ffmpeg -v verbose -i '" + j.streams[i].link + "' -c copy -flags -global_header -hls_time 10 -hls_list_size 6 -hls_wrap 10 -start_number 1 '" + j.streams[i].track + "'");
}
EOF

Output :

ffmpeg -v verbose -i 'http://playertest.longtailvideo.com/adaptive/bipbop/bipbop.m3u8' -c copy -flags -global_header -hls_time 10 -hls_list_size 6 -hls_wrap 10 -start_number 1 '/var/www/html/stream1.m3u8'
ffmpeg -v verbose -i 'https://mnmedias.api.telequebec.tv/m3u8/29880.m3u8' -c copy -flags -global_header -hls_time 10 -hls_list_size 6 -hls_wrap 10 -start_number 1 '/var/www/html/stream2.m3u8'
ffmpeg -v verbose -i 'http://www.streambox.fr/playlists/test_001/stream.m3u8' -c copy -flags -global_header -hls_time 10 -hls_list_size 6 -hls_wrap 10 -start_number 1 '/var/www/html/stream3.m3u8'

Upvotes: 0

Gilles Qu&#233;not
Gilles Qu&#233;not

Reputation: 185105

Using and :

#!/bin/bash

file="$1"
c=0
while true; do
    track=$(jq -r ".streams[$c].track" "$file" 2>/dev/null)
    link=$(jq -r ".streams[$c].link" "$file" 2>/dev/null)
    [[ ! $stream || ! $link ]] && break
    ffmpeg -v verbose -i "$link" -c copy -flags -global_header -hls_time 10 \
        -hls_list_size 6 -hls_wrap 10 -start_number 1 "$track" 
    ((c++))
done

Usage :

./script.bash file.json

Upvotes: 1

Related Questions