I would like to stack 4 videos as in the code below and add a loop for top_left.mp4 that is shorter for example.
I can't find a way to add the loop option without getting errors.
Could you help me please?
ffmpeg -i top_left.mp4 -i top_right.mp4 -i bottom_left.mp4 -i bottom_right.mp4 \
-lavfi "[0:v][1:v]hstack[top];[2:v][3:v]hstack[bottom];[top][bottom]vstack" \
2by2grid.mp4
Use -stream_loop -1 and add shortest=1 to the first hstack:
ffmpeg -stream_loop -1 -i top_left.mp4 -i top_right.mp4 -i bottom_left.mp4 -i bottom_right.mp4 -lavfi "[0:v][1:v]hstack=shortest=1[top];[2:v][3:v]hstack[bottom];[top][bottom]vstack" 2by2grid.mp4
xstack version:
ffmpeg -stream_loop -1 -i top_left.mp4 -i top_right.mp4 -i bottom_left.mp4 -i bottom_right.mp4 -lavfi "[0][1][2][3]xstack=inputs=4:layout=0_0|w0_0|0_h0|w0_h0:shortest=1" 2by2grid.mp4
Related
I want to make a long video from a single image in ffmpeg.
I need it to be fastly encodeable and at the end the video should have a small file size.
Is it possible to fill the video with frames that point to the preivous(or the first) frame with no changes?
I tried with this code, but it was slow and made a big file:
ffmpeg -loop 1 -i image.jpg -c:v libx264 -tune stillimage -shortest -preset ultrafast -t 3600 output.mp4
You can do this in two steps:
1) Encode a short loop, say, 30 seconds.
ffmpeg -loop 1 -framerate 5 -i image.jpg -pix_fmt yuv420p -c:v libx264 -t 30 looped.mp4
2) Loop the encode for desired duration.
ffmpeg -stream_loop -1 -i looped.mp4 -c copy -t 3600 output.mp4
Maybe this will help - enter it all on a single line and it will stream a single image (called test.jpg) repeatedly. See: https://stackoverflow.com/a/71885708/18795194 for my post and an explanation of the parameters.
ffmpeg
-loop 1
-fflags +genpts
-framerate 1/30
-i test.jpg
-c:v libx264
-vf fps=25
-pix_fmt yuvj420p
-crf 30
-f fifo -attempt_recovery 1 -recovery_wait_time 1
-f flv rtmp://localhost:5555/video/test
This question already has answers here:
While loop stops reading after the first line in Bash
(5 answers)
Closed 1 year ago.
I thought that my problem is trivial, but I cannot figure out, why my scripts only performing once in array.
I have a jenkins job (bash script). This job gathering hostnames and sends ssh commands, through script, using gathered info:
rm /tmp/hosts
docker exec -t tmgnt_consul_1 consul members -status=alive | grep -v Node | awk '{print $1}' | cut -d : -f1 >> /tmp/hosts
sed -i '/someunnecessaryinfo/d' /tmp/hosts
echo >> /tmp/hosts
shopt -s lastpipe
while IFS= read -r line; do
echo "host is >>$line<<";
url="http://111.111.111.111:8500/v1/catalog/nodes"
term_IP=`curl -s $url | jq -r --arg Node "${line}" '.[] | select(.Node == "'${line}'" )|.Address' --raw-output`
echo $term_IP
sudo bash -x /home/rtm/t_mgnt/check_fw $term_IP
done < /tmp/hosts
Second script:
#!/bin/bash
term_IP=$1
sudo sshpass -p 'some.pass' ssh -o StrictHostKeyChecking=no user#$term_IP "sudo test -d /root/nv9"
if [ $? != 0 ]; then
sudo sshpass -p 'some.pass' \
scp -n -o StrictHostKeyChecking=no -r /home/rtm/t_mgnt/nv9 user#$term_IP:
sudo sshpass -p 'some.pass' \
ssh -n -o StrictHostKeyChecking=no user#$term_IP "sudo mv nv9 /root/"
sudo sshpass -p 'some.pass' \
ssh -n -o StrictHostKeyChecking=no user#$term_IP "sudo dpkg -i /root/nv9/libudev0_175-0ubuntu9_amd64.deb"
sudo sshpass -p 'some.pass' \
ssh -n -o StrictHostKeyChecking=no user#$term_IP "sudo /root/nv9/DetectValidator"
else
sudo sshpass -p 'some.pass' \
ssh -n -o StrictHostKeyChecking=no user#$term_IP "sudo /root/nv9/DetectValidator"
fi
The job is working fine, and returns correct values, but only for the first element of array.
PS - I already searched through this and other sites, and - following answer didn't help me - Shell script while read line loop stops after the first line (already "ssh -n -o").
Perhaps you can point me, what I missed.
Possibly this ssh call eats your input:
sudo sshpass -p 'some.pass' ssh -o StrictHostKeyChecking=no user#$term_IP "sudo test -d /root/nv9"
^^^
Try adding -n.
I'm trying to convert a hierarcy of TIFF image files into JPG, and out of boredom, I want to do find and ffmpeg in a single file.
So I set find to invoke sh with the -s flag, like thins:
#!/bin/sh
export IFS=""
find "$#" -iname 'PROC????.tif' -exec sh -s {} + << \EOF
for t ; do
ffmpeg -y -v quiet -i $t -c:v mjpeg ${t%.*}.jpg
rm $t
done
EOF
However, there's just too many files in the directory hierarchy, and find chopped filename array into several small pieces, and sh -s was only succesfully invoked for the first argument chunk.
The question being: how could one feed such in-body command to every sh invocation in the find command?
Update
The tag "heredoc" on the question is intended for receiving answers that do not rely on external file or self-referencing through $0. It is also intended that no filename would go through string-array processing such as padding with NUL-terminator or newline, and can be directly passed as arguments.
The heredoc is being used as the input to find. I think your best bet is to not use a heredoc at all, but just use a string:
#!/bin/sh
find "$#" -iname 'PROC????.tif' -exec sh -c '
for t ; do
ffmpeg -y -v quiet -i "$t" -c:v mjpeg "${t%.*}.jpg" &&
rm "$t"
done
' sh {} +
I am re-writing your code below:-
#!/bin/bash
find "$1" -name "PROC????.tif" > /tmp/imagefile_list.txt
while read filepath
do
path=${filepath%/*}
imgfile=${filepath##*/}
jpgFile=${imgfile%.*}.jpg
cd "$path"
ffmpeg -y -v quiet -i "$imgfile" -c:v mjpeg "$jpgFile"
rm -rf $imgfile
done < /tmp/imagefile_list.txt
IF you don't want to change the current directory you can do it like below:-
#!/bin/bash
find "$1" -name "PROC????.tif" > /tmp/imagefile_list.txt
# If you list down all the .tif file use below command
# find "$1" -name "*.tif" > /tmp/imagefile_list.txt
while read filepath
do
path=${filepath%/*}
imgfile=${filepath##*/}
jpgFile=$path${imgfile%.*}.jpg
ffmpeg -y -v quiet -i "$filepath" -c:v mjpeg "$jpgFile"
rm -rf $imgfile
done < /tmp/imagefile_list.txt
rm -rf /tmp/imagefile_list.txt
How i can parse the following function command line:
The separtor is (\s-\w\s) like -c or -d or -n
C:/my app/bin/Reader.dll -n Proc_20ms -c C:/Users/Braun/Desktop/test.csv -t Continue the simulation from the first line of the csv-file -j none -V errors and warnings (default) -d ,
to:
Match1: C:/my app/bin/Reader.dll
Match2: -n
Match3: Proc_20ms
Match4: -c
Match5: C:/Users/Braun/Desktop/test.csv
Match6: -t
Match7: Continue the simulation from the first line of the csv-file
Match8: -j
Match9: none
Match10: -V
Match11: errors and warnings (default)
Match12: -d
Match13: ,
Thanks.
Just put -\w inside a capturing group and then use this regex in re.split function. capturing group is necessary, so that it would keep the delimiter (ie, only the chars present inside the capturing group).
>>> s = 'C:/my app/bin/Reader.dll -n Proc_20ms -c C:/Users/Braun/Desktop/test.csv -t Continue the simulation from the first line of the csv-file -j none -V errors and warnings (default) -d ,'
>>> for i in re.split(r'\s(-\w)\s', s):
print(i)
C:/my app/bin/Reader.dll
-n
Proc_20ms
-c
C:/Users/Braun/Desktop/test.csv
-t
Continue the simulation from the first line of the csv-file
-j
none
-V
errors and warnings (default)
-d
,
To save time, I want to segment and transcode a large video file on multiple computers.
I use ffmpeg to transcode the segments of the large video file with:
ffmpeg -i large_movie.mp4 -ss 00:00:00 -t 00:01:00 -acodec libfaac seg0.flv
ffmpeg -i large_movie.mp4 -ss 00:01:00 -t 00:01:00 -acodec libfaac seg1.flv
...
And concatenate the segments with:
ffmpeg -i concat.conf -vcodec copy -acodec copy result.flv
The content of the concat.conf:
ffsconcat version 1.0
file seg0.flv
file seg1.flv
...
Now we get a result FLV file result.flv content all the segments. But when I play this file, I found the segment boundary audio may be momentarily interrupted ! I'm sure those segments is closely associated, and the timestamp is right.
When I decode the AAC sample in segment file to a wave format, and open the wave with CoolEdit, I found at the front and the end of the file, the value of audio sample is very small (mute?) ! At the front of the file, there is about 21ms 'mute' sample. And at the end of the file, there is about 3ms 'mute' sample.
Is the mute samples result the momentarily interrupt ? How to concatenate media file containing AAC smoothly ?
After further testing, I found if you split a wave file to small wave files, then encode this small wave files to small aac file use faac:
faac -P -R 48000 -B 16 -C 2 -X -o 1.aac 1.wav
faac -P -R 48000 -B 16 -C 2 -X -o 2.aac 2.wav
faac -P -R 48000 -B 16 -C 2 -X -o 3.aac 3.wav
faac -P -R 48000 -B 16 -C 2 -X -o 4.aac 4.wav
faac -P -R 48000 -B 16 -C 2 -X -o 5.aac 5.wav
The console output like this:
[hugeice#fedora19 trans]$ faac -P -R 48000 -B 16 -C 2 -X -o 5.aac 5.wav
Freeware Advanced Audio Coder
FAAC 1.28
Quantization quality: 100
Bandwidth: 16000 Hz
Object type: Low Complexity(MPEG-2) + M/S
Container format: Transport Stream (ADTS)
Encoding 5.wav to 5.aac
frame | bitrate | elapsed/estim | play/CPU | ETA
And concatenate this small aac files to a big aac files use:
cat 1.aac 2.aac 3.aac 4.aac 5.aac > big.aac
Now, if you play the big.aac, there is a momeniary interrupt at the segment boundary!
The question becomes how segment coding and concatenate aac files smoothly ?