import 'dart:io'; import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_ali_camera/camera_export.dart'; import 'package:path_provider/path_provider.dart'; import 'package:path/path.dart' as path; void main() async { WidgetsFlutterBinding.ensureInitialized(); runApp(FirstPage()); } class FirstPage extends StatefulWidget { @override State createState() { return FirstPageState(); } } class FirstPageState extends State { @override Widget build(BuildContext context) { return MaterialApp( home: FirstState(), ); } } class FirstState extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( body: Center( child: RawMaterialButton( child: Text( "push", ), onPressed: () { Navigator.of(context).push(MaterialPageRoute(builder: (ctx) { return MyApp(); })); }, ), ), ); } } class MyApp extends StatefulWidget { @override _MyAppState createState() => _MyAppState(); } class _MyAppState extends State { final Completer _controller = Completer(); StreamSubscription _durationSubscription; // 播放进度订阅 final int duration = 5000; final double videoAspect = 9 / 16; double value = 0; bool recording = false; List recordPath = List(); @override void initState() { super.initState(); } @override void dispose() { _durationSubscription.cancel(); _dispose(); super.dispose(); } void _dispose() async { if (_controller.isCompleted) { CameraViewController controller = await _controller.future; controller.dispose(); } } void _onPlatformViewCreated(CameraViewController controller) async { await controller.create( iosTaskPath: await _findLocalPath(), recordOption: CameraRecordOption( videoWidth: 720, videoHeight: (720 * videoAspect).toInt(), quality: VideoQuality.SD)); _durationSubscription = controller.recordUpdate.listen((result) { print("record update" + result.toString()); if (result.containsKey("path")) { print("录制完成"); setState(() { recording = false; recordPath.add(result['path']); }); } }); } static Future _findLocalPath() async { final directory = Platform.isAndroid ? await getExternalStorageDirectory() : await getApplicationDocumentsDirectory(); return directory.path; } Future _record(CameraViewController controller) async { setState(() { recording = true; }); String mp4Path = path.join(await _findLocalPath(), "1.mp4"); controller.startRecord(duration, mp4Path); } void _compose(CameraViewController controller) async { if (recordPath.length == 0) return; String resultPath = path.join(await _findLocalPath(), "result.mp4"); bool success = await controller.startCompose( resultPath, null, recordPath, recordPath.map((f) => duration).toList(), CameraComposeOption( outputWidth: 480, outputHeight: (480 * videoAspect).toInt(), videoCodecs: VideoCodecs.H264_HARDWARE, quality: VideoQuality.SD, frameRate: 20, bitrate: 500000), ); print("compose result: ${success ? "successful" : "failed"}"); } @override Widget build(BuildContext context) { double width = MediaQuery.of(context).size.width; return Scaffold( backgroundColor: Colors.white, appBar: AppBar( title: const Text('Plugin example app'), ), body: ListView( // padding: EdgeInsets.symmetric(horizontal: 10), children: [ SizedBox( width: width, height: width * videoAspect, child: CameraView( onCameraViewCreated: (controller) { _controller.complete(controller); _onPlatformViewCreated(controller); }, widgetRect: Rect.fromLTWH(0, 0, width, width * videoAspect), ), ), FutureBuilder( future: _controller.future, builder: (ctx, controller) { if (controller.hasData) { return Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ IconButton( icon: Icon( Icons.play_arrow, size: 26, ), onPressed: () { if (!recording) controller.data.startPreview(); }), IconButton( icon: Icon( Icons.pause, size: 26, ), onPressed: () { if (!recording) controller.data.stopPreview(); }), IconButton( icon: Icon( Icons.switch_camera, size: 26, ), onPressed: () { if (!recording) controller.data.switchCamera(); }), IconButton( icon: Icon( recording ? Icons.stop : Icons.fiber_manual_record, size: 26, ), onPressed: () { if (!recording) _record(controller.data); }), IconButton( icon: Icon( Icons.settings, size: 26, ), onPressed: () { if (!recording) _compose(controller.data); }), ], ); } return Container(); }, ), SizedBox( height: 5, ), FutureBuilder( future: _controller.future, builder: (ctx, controller) { if (controller.hasData) { return Row( children: [ Text("美颜0-100"), Expanded( child: Slider( value: value, max: 100, onChanged: (value) { controller.data.setBeauty(value.toInt()); setState(() { this.value = value; }); }), ), ], ); } return Container(); }, ), ], ), ); } }