ffmpeg overlay voice on a song with fade in and fade out - ffmpeg

I have a fade in and fade out problem and used below code, but not completely resolve.
I have a voice as voice.mp3 name with voice_length seconds length and a song that biggest from voice.
I want mix with song from start_mix_time time.
When voice start volume should be 0.2 and when voice end, volume return to 1.0.
For example, if i have a voice by 10 s length and a song, song start playing and at position 3 s, starting to fade out to vol 0.2 and then, at 5 s, voice start over song and after 10 seconds, song fade in to vol 1 and play to end.
Here is a sample :
ffmpeg -i song1.mp3 -i voice2.mp3 -filter_complex "[0]asplit[a][b]; \
[a]atrim=duration=voice_length,volume='1-max(0.25*(t-start_mix_time-2),0)':eval=frame[pre]; \
[b]atrim=start=start_mix_time,asetpts=PTS-STARTPTS[song]; [song][1]amix=inputs=2:duration=first:dropout_transition=2[post]; \
[pre][post]concat=n=2:v=0:a=1[mixed]" \
-map "[mixed]" output.mp3
#Mulvya

For the example given - volume fades from 1 to 0.2 between t=3 & 5 and then fades back to 1 from t=15 to 17.
ffmpeg -i song.mp3 -i voice.mp3 -filter_complex
"[0]volume='1-max((t-start_fade_t)*0.8/2,0)':eval=frame:enable='between(t,3,5)',volume=0.4:eval=frame:enable='between(t,5,15)',volume='0.2+max((t-end_fade_t)*0.8/2,0)':eval=frame:enable='between(t,15,17)'[song]; \
[1]adelay=5000|5000[vo]; \
[song][vo]amix=inputs=2:duration=first:dropout_transition=0.01" \
output.mp3
Three volume filters are applied to the song - one for fade-in, one for fade-out and one during the overlay. Since the amix filter reduces the volume of its inputs, the overlay volume filter value is set to double the desired volume.

Finally, solved parametric by this :
ffmpeg -i song.mp3 -i voice.mp3 -filter_complex \
"[0]volume='1-((t-start_song_fade_out)*fade_power) + min_song_volume':eval=frame:enable='between(t,start_song_fade_out,end_song_fade_out)', \
volume=min_song_volume:eval=frame:enable='between(t,end_song_fade_out,end_song_fade_out + voice_duration - 1)', \
volume='(t-end_song_fade_out + voice_duration - 1)*fade_power + min_song_volume' \
:eval=frame:enable='between(t,end_song_fade_out + voice_duration - 1,start_song_fade_in_back + end_song_fade_out-start_song_fade_out)' \
[song]; [1]adelay='(end_song_fade_out*1000)'|'(end_song_fade_out*1000)'[vo]; \
[song][vo]amix=inputs=2:duration=first:dropout_transition=0.01" -id3v2_version 3 output.mp3

Related

ffmpeg - create a morph video between 2 images (png solid hex color) 0.55 seconds for a length of 10 seconds

currently i create with imagick (convert -size 640x480 xc:#FF000 hex1.png and hex2.png) 2 png images and save both png files.
now i need the following (but i have no idea how i can do that (maybe ffmpeg?)):
create a video 640x480 for example a length of 10 seconds like this method:
0.00s (hex1) > 0.55s (hex2) > 1.10s (hex1) > 1.65s (hex2) > 2.2s (hex1).... until the 10 seconds has reached.
the hex1 and hex2 images should always morph/fade from hex1 => hex2 => hex1, ...
but the time is very critical. the time must be exact always have 0.55.
maybe i can create on same way direct the HEX colors without creating first a png image for that purposes.
can anybody helps me how i can do that best way?
thank you so much and many greets iceget
currently i have created only a single image with that function:
ffmpeg -loop 1 -i hex1.png -c:v libx264 -t 10 -pix_fmt yuv420p video.mp4
Here is one of the approaches to achieving your goal without pre-creation of images:
ffmpeg -hide_banner -y \
-f lavfi -i color=c=0x0000ff:size=640x480:duration=0.55:rate=20 \
-filter_complex \
"[0]fade=type=out:duration=0.55:color=0xffff00[fade_first_color]; \
[fade_first_color]split[fade_first_color1][fade_first_color2]; \
[fade_first_color1]reverse[fade_second_color]; \
[fade_first_color2][fade_second_color]concat[fade_cycle]; \
[fade_cycle]loop=loop=10/(0.55*2):size=0.55*2*20,trim=duration=10" \
flicker.mp4
Since loop filter operates with frames, not seconds, and you have time constraints, you may choose only the few FPS rates correspondig to the integer number of frames that fit in the 0.55 seconds period (e.g. 20, 40, 60).
The filtergraph is self-explanable.
The result of such command will be like this:
Almost universal way (added in response to the OP's new questions)
#!/bin/bash
# Input parameters
color_1=0x0000ff
color_2=0xffff00
segment_duration=0.55
total_duration=10
# Magic calculations
sd_numerator=${segment_duration#*.}
sd_denominator=$(( 10**${#sd_numerator} ))
FPS=$(ffprobe -v error -f lavfi "aevalsrc=print('$sd_denominator/gcd($sd_numerator,$sd_denominator)'\,16):s=1:d=1" 2>&1)
FPS=${FPS%.*}
# Preparing the output a little bit longer than total_duration
# and mark the cut point with the forced keyframe
ffmpeg -hide_banner -y \
-f lavfi -i color=c=$color_1:size=640x480:duration=$segment_duration:rate=$FPS \
-filter_complex \
"[0]fade=type=out:duration=$segment_duration:color=$color_2[fade_first_color]; \
[fade_first_color]split[fade_first_color1][fade_first_color2]; \
[fade_first_color1]reverse[fade_second_color]; \
[fade_first_color2][fade_second_color]concat[fade_cycle]; \
[fade_cycle]loop=loop=ceil($total_duration/($segment_duration*2))+1: \
size=$segment_duration*2*$FPS,fps=fps=25" \
-force_key_frames $total_duration \
flicker_temp.mp4
# Fine cut of total_duration
ffmpeg -hide_banner -y -i flicker_temp.mp4 -to $total_duration flicker_${total_duration}s.mp4
# Clean up
rm flicker_temp.mp4

What are supported ffmpeg rtp_mpegts Muxer options? (mpegts Muxer options are ignored)

I created a UDP stream with -f mpegts and some options like -mpegts_transport_stream_id.
I received the stream with "StreamXpert - Real-time stream analyzer" that shows all options are in the output. See my ffmpeg parameters and the StreamXpert at the end.
The same Muxer options seem to be ignored with -f rtp_mpegts.
I have tried to use -f mpegts and pipe it to -f rtp_mpegts like so:
ffmpeg -i ... -f mpegts pipe: | ffmpeg pipe: -c copy -f rtp_mpegts "rtp://239.1.1.9:1234?pkt_size=1316"
The options are still ignored.
This ticket "support options for MPEGTS muxer when using RTP_MPEGTS" also notices the ignored option. Furthermore in this comment, "thovo" gives an analysis and suggests a solution.
Obviously the problem still exists. Anybody found a workaround for this?
My additional question: I have not questioned if my project really needs rtp in the first place. Maybe my coworker didn't know better and requested rtp when udp would be sufficient as well.
The aim was to receive the RTP stream with a TV using DVB via IP. This was successful an a Panasonic TV.
The SAT>IP Specification on page 10 requires rtp for Media Transport:
The SAT>IP protocol makes use of:
UPnP for Addressing, Discovery and Description,
RTSP or HTTP for Control,
RTP or HTTP for Media Transport.
Is udp out of the equation?
ffmpeg: (all options are in the output with -f mpegts)
(HEX to decimal: 0x005A = 90, 0x005B = 91 0x005C = 92, 0x005D = 93, 0x005E= 94)
ffmpeg -f lavfi -i testsrc \
-r 25 \
-c:v libx264 \
-pix_fmt yuv420p \
-profile:v main -level 3.1 \
-preset veryfast \
-vf scale=1280:720,setdar=dar=16/9 \
-an \
-bsf:v h264_mp4toannexb \
-flush_packets 0 \
-b:v 4M \
-muxrate 8M \
-pcr_period 20 \
-pat_period 0.10 \
-sdt_period 0.25 \
-metadata:s:a:0 language=nya \
-mpegts_flags +pat_pmt_at_frames \
-mpegts_transport_stream_id 0x005A \
-mpegts_original_network_id 0x005B \
-mpegts_service_id 0x005C \
-mpegts_pmt_start_pid 0x005D \
-mpegts_start_pid 0x005E \
-mpegts_service_type advanced_codec_digital_hdtv \
-metadata service_provider='WI' \
-metadata service_name='W' \
-mpegts_flags system_b -flush_packets 0 \
-f mpegts "udp://239.1.1.10:1234?pkt_size=1316"
StreamXpert Output:
-mpegts_transport_stream_id = Transport Stream ID (yellow text highlight)
-mpegts_original_network_id = Original Network ID, onw (green text highlight)
-mpegts_service_id = Program, service (pink text highlight)
-mpegts_pmt_start_pid = PMT PID, Table PID (turquoise text highlight)
-mpegts_start_pid = PID, PCR PID (red text highlight)
-mpegts_service_type = service type (blue text)
service_name = Service name (orange text)
service_provider = Service provider (pink text)

ffmpeg choose exact frame from long film strip

I'm working with ffmpeg to choose the better thumbnail for my video. and the selection would be based on the slider.
as per the requirement multiple thumbnails not needed just a single long film image and with the help of slider select the thumbnail and save it.
i used below command to get the long strip thumbnail.
ffmpeg -loglevel panic -y -i "video.mp4" -frames 1 -q:v 1 -vf "select=not(mod(n\,40)),scale=-1:120,tile=100x1" video_preview.jpg
I followed the instructions from this tutorial
I'm able to get the long film image:
This is working fine, they moving the image in slider which is fine.
My question is how can I select a particular frame from that slider / film strip. How can I calculate the exact time duration from the slider and then execute a command to extract that frame?
In one of my project I implemented the below scenario. In the code where I'm getting Video duration from the ffmgpeg command, if duration is less than 0.5 second than I set a new thumbnail interval for the same. In your case you should set time interval for the thumbnail creation. Hope this will help you.
$dur = 'ffprobe -i '.$video.' -show_entries format=duration -v quiet -of csv="p=0"';
$duration= exec($dur);
if($duration < 0.5) {
$interval = 0.1;
} else {
$interval = 0.5;
}
screenshot size
$size = '320x240';
ffmpeg command
$cmd = "ffmpeg -i $video -deinterlace -an -ss $interval -f mjpeg -t 1 -r 1 -y $image";
exec($cmd);
You can try this:
ffmpeg -vsync 0 -ss duration -t 0.0001 -noaccurate_seek -i filename -ss 00:30 -t 0.0001 -noaccurate_seek -i filename -filter_complex [0:v][1:v] concat=n=2[con];[con]scale=80:60:force_original_aspect_ratio=decrease[sc];[sc]tile=2x1[out] -map [out]:v -frames 1 -f image2 filmStrip.jpg
2 frame

How to generate tile with video thumbnails with right timecode

I'm using FFMPEG library for generating video thumbnails every 5 sec with time codes using following command:
ffmpeg \
-i 20051210-w50s.flv \
-y \
-frames 1 \
-vf " \
select=not(mod(t\,5)), \
scale=320:-1, \
drawtext=fontfile=/usr/share/fonts/dejavu/DejaVuSans-Bold.ttf: \
timecode='00\\:00\\:00\\:00': r=25: fontcolor=white: x=220: y=220: box=1: boxcolor=black#0.5, \
tile=5x2" \
-vsync 0 \
out.jpg
It gererate right thumbnails tile, but timecodes is wrong. How to solve this issue?
The drawtext filter is not referencing the timestamp. It uses a simple counter that increments the timecode for each new frame. So, the way to do this is to draw each timecode and then drop frames.
ffmpeg \
-i 20051210-w50s.flv \
-y \
-frames 1 \
-vf " \
scale=320:-1, \
drawtext=fontfile=/usr/share/fonts/dejavu/DejaVuSans-Bold.ttf: \
timecode='00\\:00\\:00\\:00': r=25: fontcolor=white: x=220: y=220: box=1: boxcolor=black#0.5, \
select=not(mod(t\,5)), \
tile=5x2" \
-vsync 0 \
out.jpg
Drawing text for each frame before selecting the useful ones solves the problem but also introduces performance losses. I made an experiment about it, and the result confirmed my guess.
A better solution would be keeping calling "select" first and using text='%{pts:hms}' instead of timecode.
ffmpeg \
-i 20051210-w50s.flv \
-y \
-frames 1 \
-vf \
"select=not(mod(t\,5)), \
scale=320:-1, \
drawtext=text='%{pts:hms}': fontfile=/usr/share/fonts/dejavu/DejaVuSans-Bold.ttf: \
fontcolor=white: x=220: y=220: box=1: boxcolor=black#0.5, \
tile=5x2" \
-vsync 0 \
out.jpg

ffmpeg live stream only outputting 240p

I am having trouble rescaling the resolution of a video with complex filters to 720p, adding the scale to reference the video seems to cause an error
ffmpeg -re -i "https://mnmedias.api.telequebec.tv/m3u8/29880.m3u8" -i
./public/images/ACE.png -i ./public/images/logo2.jpg -i
./public/images/crunchy.png -i ./public/images/red.jpg -filter_complex "
[0]scale=1280:720[ovrl0], [va][ovrl0][v0];[1]scale=40:40[ovrl1], [v0]
[ovrl1] overlay=580:10:enable='lt(mod(t,40),10)'[v1];[2]scale=40:40[ovrl2],
[v1][ovrl2] overlay=580:10:enable='between(mod(t,40),10,20)'[v2];
[3]scale=40:40[ovrl3], [v2][ovrl3]
overlay=580:10:enable='gt(mod(t,40),20)'[v3];[4]scale=40:40[ovrl4], [v3]
[ovrl4] overlay=580:10:enable='gt(mod(t,40),30)'" -acodec aac -vcodec
libx264 -f flv "rtmp://a.rtmp.youtube.com/live2/2222-2222-2222-2222"
error output is [AVFilterGraph # 0x7f964163e9a0] No such filter: ''
Your filtergraph is malformed:
, [va][ovrl0][v0] appears to be a typo and is not applied to any filter.
Your first scale filter is referencing [v0] but [v0] does not exist (other than the orphaned declaration in the typo).
, is use to join linear filters to create a filterchain. ; is used to separate distinct filterchains. You're using , instead of ; in some locations. See FFmpeg Filter Syntax.
I'm guessing you want something like:
-filter_complex \
"[0]scale=1280:720[ovrl0]; \
[1]scale=40:40[ovrl1]; \
[2]scale=40:40[ovrl2]; \
[3]scale=40:40[ovrl3]; \
[4]scale=40:40[ovrl4]; \
[ovrl0][ovrl1] overlay=580:10:enable='lt(mod(t,40),10)'[v1]; \
[v1][ovrl2] overlay=580:10:enable='between(mod(t,40),10,20)'[v2]; \
[v2][ovrl3] overlay=580:10:enable='gt(mod(t,40),20)'[v3]; \
[v3][ovrl4] overlay=580:10:enable='gt(mod(t,40),30)'"

Resources