applyTextAndEffects static method
Future<String>
applyTextAndEffects({
- required String inputPath,
- required List<
VideoEditorClip> clips, - required List<
VideoTextOverlay> textOverlays, - required List<
VideoEffectOverlay> effectOverlays,
Burns clip effects, effect overlays and text into an existing video.
Implementation
static Future<String> applyTextAndEffects({
required String inputPath,
required List<VideoEditorClip> clips,
required List<VideoTextOverlay> textOverlays,
required List<VideoEffectOverlay> effectOverlays,
}) async {
final hasClipEffects = clips.any((c) => c.effect != VideoEditorEffect.none);
if (!hasClipEffects && textOverlays.isEmpty && effectOverlays.isEmpty) {
return inputPath;
}
final directory = await getTemporaryDirectory();
final timestamp = DateTime.now().millisecondsSinceEpoch;
final outputPath = '${directory.path}/prixa_effects_$timestamp.mp4';
final fontPath = await RenderFilterBuilder.getFontPath();
String between(Duration start, Duration end) =>
"'between(t,${(start.inMilliseconds / 1000).toStringAsFixed(3)},"
"${(end.inMilliseconds / 1000).toStringAsFixed(3)})'";
final filters = <String>[];
var accumulated = Duration.zero;
for (final clip in clips) {
final end = accumulated + clip.effectiveDuration;
for (final f in RenderFilterBuilder.effectFilterChain(clip.effect)) {
filters.add('$f:enable=${between(accumulated, end)}');
}
accumulated = end;
}
for (final overlay in effectOverlays) {
for (final f in RenderFilterBuilder.effectFilterChain(overlay.effect)) {
filters.add(
'$f:enable=${between(overlay.startTime, overlay.effectiveEndTime)}',
);
}
}
for (final overlay in textOverlays) {
filters.add(
RenderFilterBuilder.textOverlayToDrawText(overlay, fontPath ?? ''),
);
}
final session = await FFmpegKit.executeWithArguments([
'-y',
'-i', inputPath,
'-vf', filters.join(','),
'-map', '0:v:0',
'-map', '0:a?',
...videoCodecArgs(
canvas: const Size(1080, 1920),
fps: 30,
quality: ExportQuality.standard,
preview: false,
),
'-pix_fmt', 'yuv420p',
'-c:a', 'aac',
'-b:a', '192k',
'-movflags', '+faststart',
outputPath,
]);
final returnCode = await session.getReturnCode();
if (!ReturnCode.isSuccess(returnCode)) {
final logs = await session.getLogsAsString();
throw RenderException('Text/effects export failed', logs);
}
return outputPath;
}