composeVideo method
Future<VideoTask>
composeVideo({
- required String inputVideoPath,
- String? outputVideoPath,
- Uint8List? watermarkImage,
- String? text,
- String anchor = 'bottomRight',
- double margin = 16.0,
- String marginUnit = 'px',
- double offsetX = 0.0,
- double offsetY = 0.0,
- String offsetUnit = 'px',
- double widthPercent = 0.18,
- double opacity = 0.6,
- String codec = 'h264',
- int? bitrateBps,
- double? maxFps,
- int? maxLongSide,
override
Starts composing a watermark over a video file on iOS. Returns a VideoTask that exposes a progress stream and completion future.
Implementation
@override
Future<VideoTask> composeVideo({
required String inputVideoPath,
String? outputVideoPath,
Uint8List? watermarkImage,
String? text,
String anchor = 'bottomRight',
double margin = 16.0,
String marginUnit = 'px',
double offsetX = 0.0,
double offsetY = 0.0,
String offsetUnit = 'px',
double widthPercent = 0.18,
double opacity = 0.6,
String codec = 'h264',
int? bitrateBps,
double? maxFps,
int? maxLongSide,
}) async {
_ensureCallbacksRegistered();
final taskId = _genTaskId();
final ctrl = StreamController<double>.broadcast();
final completer = Completer<VideoResult>();
_tasks[taskId] = _VideoTaskState(ctrl, completer);
pigeon.ComposeVideoRequest req = pigeon.ComposeVideoRequest(
taskId: taskId,
inputVideoPath: inputVideoPath,
outputVideoPath: outputVideoPath,
watermarkImage: watermarkImage,
text: text,
anchor: _anchorFromString(anchor),
margin: margin,
marginUnit: _unitFromString(marginUnit),
offsetX: offsetX,
offsetY: offsetY,
offsetUnit: _unitFromString(offsetUnit),
widthPercent: widthPercent,
opacity: opacity,
codec: (codec == 'hevc') ? pigeon.VideoCodec.hevc : pigeon.VideoCodec.h264,
bitrateBps: bitrateBps,
maxFps: maxFps,
maxLongSide: maxLongSide,
);
// Fire-and-forget; completion will also complete the future
unawaited(pigeon.WatermarkApi().composeVideo(req).then((res) {
// Fallback completion in case onVideoCompleted wasn't received
final st = _tasks[res.taskId];
if (st != null && !st.completer.isCompleted) {
st.ctrl.close();
st.completer.complete(VideoResult(
path: res.outputVideoPath,
width: res.width,
height: res.height,
durationMs: res.durationMs,
codec: res.codec == pigeon.VideoCodec.hevc ? 'hevc' : 'h264',
));
_tasks.remove(res.taskId);
}
}).catchError((e, st) {
// If error surfaces via returned Future
final s = _tasks.remove(taskId);
if (s != null && !s.completer.isCompleted) {
s.ctrl.addError(e, st);
s.ctrl.close();
s.completer.completeError(e, st);
}
}));
return VideoTask(
taskId: taskId,
progress: ctrl.stream,
done: completer.future,
cancel: () async {
await pigeon.WatermarkApi().cancel(taskId);
},
);
}