Reputation: 185
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
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
Reputation: 185105
Using nodejs to generate the shell 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
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
Reputation: 185105
#!/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
./script.bash file.json
Upvotes: 1