Orientação gerada a partir de informações públicas. Apenas para referência.
Um pacote Flutter que permite codificação eficiente de quadros brutos RGB em vídeos MP4 usando codificadores H.264 de hardware no Android, iOS e macOS. Ele suporta entrada de áudio PCM para criar faixas de áudio M4A, tornando-o ideal para gravação e processamento de vídeo em tempo real. O pacote aproveita os recursos nativos da plataforma para entregar alto desempenho com uso mínimo de CPU. Projetado para desenvolvedores que constroem aplicações multimídia que exigem codificação de vídeo rápida e com baixa latência.
Casos de uso
Gravação de vídeo em tempo real
Captura de transmissão ao vivo
Fluxos de trabalho de edição de vídeo
Compressão de vídeo no dispositivo
Sincronização de áudio e vídeo
Principais recursos
Codificação H.264 acelerada por hardware
Suporte de áudio PCM
Compatibilidade multiplataforma
Baixo custo de CPU
API simples para entrada de quadro
Indicado para
Aplicativos de vídeo móvel
Aplicações baseadas em câmera
Ferramentas de processamento de mídia
Sistemas de vídeo embarcados
Gravação de alto desempenho
Considerações
Requer permissões de plataforma nativa
Limitado ao formato de entrada RGB
Nenhum fallback de software para codificação
Configuração específica da plataforma necessária
Sincronização de áudio exige tempo preciso
README original
Snapshot do README original do repositório-fonte vinculado. Consulte o repositório para o conteúdo mais recente.
Quickly encode raw RGB images & PCM audio to MP4 video using the system h264 encoder
No Dependencies
FlutterQuickVideoEncoder has zero dependencies besides Flutter, Android, iOS, and MacOS themselves. No FFMPEG.
We use AVFoundation on iOS and MediaCodec on Android. These are native system libraries.
For encoding raw RGB pixels
Unlike the video_compress package, this package takes raw rgb pixel buffers as input, not video files.
⭐ Stars ⭐
Please star this repo & on pub.dev. We all benefit from having a larger community.
Usage
awaitFlutterQuickVideoEncoder.setup(
width: 1920,
height: 1080,
fps: 60,
videoBitrate: 2500000,
audioChannels: 1,
audioBitrate: 64000,
sampleRate: 44100,
filepath: "/documents/video.mp4", // output file
);
for(int i = 0; i < frameCount; i++) {
Uint8List rgba = _renderVideoFrame(i); // your video functionUint8List pcm = _renderAudioFrame(i); // your audio functionawaitFlutterQuickVideoEncoder.appendVideoFrame(rgba);
awaitFlutterQuickVideoEncoder.appendAudioFrame(pcm);
}
awaitFlutterQuickVideoEncoder.finish();
Example App
Enable the platforms you need.
cd ./example
flutter config --enable-macos-desktop
flutter config --enable-android
flutter config --enable-ios
flutter create .
flutter run
Create video frames using ui.Image
The easiest way to render a video frame is to use Flutter!
For example, you can render an RGBA frame using ui.Image
Future<Uint8List> _generateVideoFrame(int frameIndex) async {
constint boxSize = 50; // Size of the moving box// Calculate the box positionint boxX = (frameIndex * 5) % width;
int boxY = (frameIndex * 5) % height;
// Paint the moving boxfinal recorder = ui.PictureRecorder();
final canvas = Canvas(recorder);
final paint = Paint();
// Draw a white background
paint.color = Colors.white;
canvas.drawRect(Rect.fromLTWH(0, 0, width.toDouble(), height.toDouble()), paint);
// Draw the blue box
paint.color = Colors.blue;
canvas.drawRect(Rect.fromLTWH(boxX.toDouble(), boxY.toDouble(), boxSize.toDouble(), boxSize.toDouble()), paint);
// Convert canvas to imagefinal picture = recorder.endRecording();
final img = await picture.toImage(width, height);
// Convert the image to a byte arrayfinal byteData = await img.toByteData(format: ui.ImageByteFormat.rawRgba);
return byteData!.buffer.asUint8List();
}
Create video frames from Widgets
You can also create video frames from widgets, using RenderRepaintBoundary
import'dart:ui'as ui;
import'package:flutter/material.dart';
import'dart:typed_data';
classMyWidgetextendsStatefulWidget{
@override_MyWidgetStatecreateState() => _MyWidgetState();
}
class_MyWidgetStateextendsState<MyWidget> {
GlobalKey repaintBoundaryKey = GlobalKey();
@overrideWidgetbuild(BuildContext context) {
returnRepaintBoundary(
key: repaintBoundaryKey,
child: YourWidget(), // Replace with your actual widget
);
}
// you would then call appendVideoFrame with this dataFuture<Uint8List?> captureWidgetAsRGBA() async {
try {
RenderRepaintBoundary boundary = repaintBoundaryKey.currentContext!.findRenderObject() asRenderRepaintBoundary;
ui.Image image = await boundary.toImage(pixelRatio: 1.0);
ByteData? byteData = await image.toByteData(format: ui.ImageByteFormat.rawRgba);
return byteData?.buffer.asUint8List();
} catch (e) {
print(e);
returnnull;
}
}
}