Add intro videos, outro videos, and watermarks to any video processing. These features work globally across the entire package - single videos, clips, HLS streams, etc.
Video composition allows you to:
- Add intro - Prepend a video before your content
- Add outro - Append a video after your content
- Add watermark - Overlay an image/logo on your video
These work with any FFmpeg operation: single videos, batch clips, HLS exports, format conversions, etc.
use Ritechoice23\FluentFFmpeg\Facades\FFmpeg;
FFmpeg::fromPath('video.mp4')
->withWatermark('logo.png', 'top-right')
->save('branded.mp4');Watermark Positions:
top-left- Top left corner (10px padding)top-right- Top right corner (default)bottom-left- Bottom left cornerbottom-right- Bottom right cornercenter- Center of video
FFmpeg::fromPath('video.mp4')
->withIntro('intro.mp4')
->save('with-intro.mp4');FFmpeg::fromPath('video.mp4')
->withOutro('outro.mp4')
->save('with-outro.mp4');FFmpeg::fromPath('video.mp4')
->withIntro('brand-intro.mp4')
->withOutro('cta-outro.mp4')
->withWatermark('logo.png', 'bottom-right')
->save('complete.mp4');FFmpeg::fromPath('video.avi')
->withIntro('intro.mp4')
->withWatermark('logo.png')
->videoCodec('libx264')
->save('output.mp4');FFmpeg::fromPath('video.mp4')
->withIntro('intro.mp4')
->withWatermark('logo.png', 'top-right')
->exportForHLS()
->addFormat('1080p')
->addFormat('720p')
->save('stream.m3u8');FFmpeg::fromPath('long-video.mp4')
->clips([
['start' => '00:00:10', 'end' => '00:00:30'],
['start' => '00:01:00', 'end' => '00:01:20'],
])
->withIntro('intro.mp4') // Added to EACH clip
->withOutro('outro.mp4') // Added to EACH clip
->withWatermark('logo.png') // Added to EACH clip
->save('clip.mp4');
// Creates: clip_1.mp4, clip_2.mp4 (each with intro/outro/watermark)FFmpeg::fromPath('4k-video.mp4')
->resolution(1920, 1080)
->withWatermark('logo.png')
->videoBitrate('5000k')
->save('1080p-branded.mp4');FFmpeg::fromPath('video.mp4')
->addFilter('fade', ['in', 0, 30])
->withIntro('intro.mp4')
->withWatermark('logo.png')
->save('output.mp4');// Logo in top-left
->withWatermark('logo.png', 'top-left')
// Brand in top-right
->withWatermark('brand.png', 'top-right')
// Copyright in bottom-right
->withWatermark('copyright.png', 'bottom-right')
// Centered badge
->withWatermark('badge.png', 'center')- PNG with transparency - Recommended (supports alpha channel)
- PNG with solid background - Works well
- JPG - Works but no transparency
// Transparent logo (best)
->withWatermark('logo-transparent.png', 'top-right')For best results, intro/outro videos should match your source video:
// Good: Same resolution and framerate
// Source: 1920x1080 @ 30fps
// Intro: 1920x1080 @ 30fps
// Outro: 1920x1080 @ 30fps
FFmpeg::fromPath('video-1080p-30fps.mp4')
->withIntro('intro-1080p-30fps.mp4')
->withOutro('outro-1080p-30fps.mp4')
->save('complete.mp4');If specs don't match, FFmpeg will handle it, but may require re-encoding:
// Source: 1920x1080 @ 30fps
// Intro: 1280x720 @ 24fps (will be scaled/adjusted)
FFmpeg::fromPath('video.mp4')
->withIntro('intro-720p.mp4') // Auto-scaled to 1080p
->save('output.mp4');// Add brand intro and watermark to all videos
FFmpeg::fromPath($video)
->withIntro(public_path('brand/intro.mp4'))
->withWatermark(public_path('brand/logo.png'), 'top-right')
->save($output);// Instagram-ready with intro, outro, and watermark
FFmpeg::fromPath('content.mp4')
->withIntro('instagram-intro.mp4')
->withOutro('follow-cta.mp4')
->withWatermark('handle.png', 'bottom-left')
->resolution(1080, 1080) // Square for Instagram
->save('instagram-post.mp4');// Social media content
FFmpeg::fromPath('video.mp4')
->withIntro('intro.mp4')
->withWatermark('logo.png', 'top-right')
->save('social.mp4');
// Educational/Course content
FFmpeg::fromPath('lesson.mp4')
->withIntro('course-intro.mp4')
->withOutro('next-lesson.mp4')
->withWatermark('school-logo.png', 'bottom-right')
->save('tutorial.mp4');- Fast: Intro/outro only (copy codec when specs match)
- Slower: Watermark (requires re-encoding)
- Match specs: Use intro/outro with same resolution/framerate for optimal speed
Intro/Outro: Any format (MP4 recommended), ideally matching source resolution/framerate
Watermark: PNG with transparency preferred, appropriately sized for video
Perfect for creating professional, branded video content at scale!
Combine cover art with audio waveform overlay:
// Generate waveform
FFmpeg::fromPath('audio.mp3')
->waveform(['width' => 800, 'height' => 200, 'color' => 'cyan'])
->save('wave.png');
// Overlay on cover art
FFmpeg::fromPath('cover.jpg')
->addInput('wave.png')
->addInput('audio.mp3')
->overlay(['x' => '(W-w)/2', 'y' => 'H-h-50']) // Center, 50px from bottom
->resolution(1920, 1080)
->save('audio-video.mp4');For full audio visualization documentation, see Helper Methods.
The overlay() method gives you precise control over compositing videos and images. Use it for Picture-in-Picture effects, custom watermarks, and multi-layer compositions.
// Overlay a logo (second input) on main video
FFmpeg::fromPath('video.mp4')
->addInput('logo.png')
->overlay(['x' => 20, 'y' => 20])
->save('output.mp4');// Add webcam feed in corner of screen share
FFmpeg::fromPath('screenshare.mp4')
->addInput('webcam.mp4')
->overlay([
'x' => 'W-w-20', // 20px from right
'y' => 'H-h-20', // 20px from bottom
'width' => 320,
'height' => 240
])
->save('presentation.mp4');x: Horizontal position (pixels or FFmpeg expression likeW-w-10for right edge)y: Vertical position (pixels or FFmpeg expression likeH-h-10for bottom edge)width: Scale overlay to this width (optional)height: Scale overlay to this height (optional)
// Center overlay
->overlay(['x' => '(W-w)/2', 'y' => '(H-h)/2'])
// Top-left with padding
->overlay(['x' => 10, 'y' => 10])
// Bottom-right corner
->overlay(['x' => 'W-w-10', 'y' => 'H-h-10'])// Overlay multiple elements (requires complex filters)
FFmpeg::fromPath('video.mp4')
->addInput('watermark.png')
->addInput('logo.png')
->overlay(['x' => 10, 'y' => 10]) // First overlay
->save('output.mp4');Note: withWatermark() is a convenience method that uses overlay() internally with predefined positions.
The concat() method allows you to join multiple videos into a single output file.
FFmpeg::fromPath('part1.mp4')
->concat(['part2.mp4', 'part3.mp4'])
->save('complete.mp4');// Combine intro, main content, and outro
FFmpeg::fromPath('intro.mp4')
->concat([
'main-content.mp4',
'outro.mp4'
])
->save('final-video.mp4');// Concatenate then apply watermark
FFmpeg::fromPath('clip1.mp4')
->concat(['clip2.mp4', 'clip3.mp4'])
->withWatermark('logo.png', 'top-right')
->save('compilation.mp4');- All videos should have the same resolution, codec, and framerate for best results
- If specs differ, FFmpeg will handle conversion but may require re-encoding
Note: For intro/outro workflows, use withIntro() and withOutro() which provide a simpler API.