main.dart 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. import 'dart:io';
  2. import 'dart:async';
  3. import 'package:flutter/material.dart';
  4. import 'package:flutter_ali_camera/camera_export.dart';
  5. import 'package:path_provider/path_provider.dart';
  6. import 'package:path/path.dart' as path;
  7. void main() async {
  8. WidgetsFlutterBinding.ensureInitialized();
  9. runApp(FirstPage());
  10. }
  11. class FirstPage extends StatefulWidget {
  12. @override
  13. State<StatefulWidget> createState() {
  14. return FirstPageState();
  15. }
  16. }
  17. class FirstPageState extends State<FirstPage> {
  18. @override
  19. Widget build(BuildContext context) {
  20. return MaterialApp(
  21. home: FirstState(),
  22. );
  23. }
  24. }
  25. class FirstState extends StatelessWidget {
  26. @override
  27. Widget build(BuildContext context) {
  28. return Scaffold(
  29. body: Center(
  30. child: RawMaterialButton(
  31. child: Text(
  32. "push",
  33. ),
  34. onPressed: () {
  35. Navigator.of(context).push(MaterialPageRoute(builder: (ctx) {
  36. return MyApp();
  37. }));
  38. },
  39. ),
  40. ),
  41. );
  42. }
  43. }
  44. class MyApp extends StatefulWidget {
  45. @override
  46. _MyAppState createState() => _MyAppState();
  47. }
  48. class _MyAppState extends State<MyApp> {
  49. final Completer<CameraViewController> _controller = Completer<CameraViewController>();
  50. StreamSubscription _durationSubscription; // 播放进度订阅
  51. final int duration = 5000;
  52. final double videoAspect = 9 / 16;
  53. double value = 0;
  54. bool recording = false;
  55. List<String> recordPath = List();
  56. @override
  57. void initState() {
  58. super.initState();
  59. }
  60. @override
  61. void dispose() {
  62. _durationSubscription.cancel();
  63. _dispose();
  64. super.dispose();
  65. }
  66. void _dispose() async {
  67. if (_controller.isCompleted) {
  68. CameraViewController controller = await _controller.future;
  69. controller.dispose();
  70. }
  71. }
  72. void _onPlatformViewCreated(CameraViewController controller) async {
  73. await controller.create(
  74. iosTaskPath: await _findLocalPath(),
  75. recordOption: CameraRecordOption(
  76. videoWidth: 720, videoHeight: (720 * videoAspect).toInt(), quality: VideoQuality.SD));
  77. _durationSubscription = controller.recordUpdate.listen((result) {
  78. print("record update" + result.toString());
  79. if (result.containsKey("path")) {
  80. print("录制完成");
  81. setState(() {
  82. recording = false;
  83. recordPath.add(result['path']);
  84. });
  85. }
  86. });
  87. }
  88. static Future<String> _findLocalPath() async {
  89. final directory = Platform.isAndroid
  90. ? await getExternalStorageDirectory()
  91. : await getApplicationDocumentsDirectory();
  92. return directory.path;
  93. }
  94. Future<void> _record(CameraViewController controller) async {
  95. setState(() {
  96. recording = true;
  97. });
  98. String mp4Path = path.join(await _findLocalPath(), "1.mp4");
  99. controller.startRecord(duration, mp4Path);
  100. }
  101. void _compose(CameraViewController controller) async {
  102. if (recordPath.length == 0) return;
  103. String resultPath = path.join(await _findLocalPath(), "result.mp4");
  104. bool success = await controller.startCompose(
  105. resultPath,
  106. null,
  107. recordPath,
  108. recordPath.map((f) => duration).toList(),
  109. CameraComposeOption(
  110. outputWidth: 480,
  111. outputHeight: (480 * videoAspect).toInt(),
  112. videoCodecs: VideoCodecs.H264_HARDWARE,
  113. quality: VideoQuality.SD,
  114. frameRate: 20,
  115. bitrate: 500000),
  116. );
  117. print("compose result: ${success ? "successful" : "failed"}");
  118. }
  119. @override
  120. Widget build(BuildContext context) {
  121. double width = MediaQuery.of(context).size.width;
  122. return Scaffold(
  123. backgroundColor: Colors.white,
  124. appBar: AppBar(
  125. title: const Text('Plugin example app'),
  126. ),
  127. body: ListView(
  128. // padding: EdgeInsets.symmetric(horizontal: 10),
  129. children: <Widget>[
  130. SizedBox(
  131. width: width,
  132. height: width * videoAspect,
  133. child: CameraView(
  134. onCameraViewCreated: (controller) {
  135. _controller.complete(controller);
  136. _onPlatformViewCreated(controller);
  137. },
  138. widgetRect: Rect.fromLTWH(0, 0, width, width * videoAspect),
  139. ),
  140. ),
  141. FutureBuilder(
  142. future: _controller.future,
  143. builder: (ctx, controller) {
  144. if (controller.hasData) {
  145. return Row(
  146. mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  147. children: <Widget>[
  148. IconButton(
  149. icon: Icon(
  150. Icons.play_arrow,
  151. size: 26,
  152. ),
  153. onPressed: () {
  154. if (!recording) controller.data.startPreview();
  155. }),
  156. IconButton(
  157. icon: Icon(
  158. Icons.pause,
  159. size: 26,
  160. ),
  161. onPressed: () {
  162. if (!recording) controller.data.stopPreview();
  163. }),
  164. IconButton(
  165. icon: Icon(
  166. Icons.switch_camera,
  167. size: 26,
  168. ),
  169. onPressed: () {
  170. if (!recording) controller.data.switchCamera();
  171. }),
  172. IconButton(
  173. icon: Icon(
  174. recording ? Icons.stop : Icons.fiber_manual_record,
  175. size: 26,
  176. ),
  177. onPressed: () {
  178. if (!recording) _record(controller.data);
  179. }),
  180. IconButton(
  181. icon: Icon(
  182. Icons.settings,
  183. size: 26,
  184. ),
  185. onPressed: () {
  186. if (!recording) _compose(controller.data);
  187. }),
  188. ],
  189. );
  190. }
  191. return Container();
  192. },
  193. ),
  194. SizedBox(
  195. height: 5,
  196. ),
  197. FutureBuilder(
  198. future: _controller.future,
  199. builder: (ctx, controller) {
  200. if (controller.hasData) {
  201. return Row(
  202. children: <Widget>[
  203. Text("美颜0-100"),
  204. Expanded(
  205. child: Slider(
  206. value: value,
  207. max: 100,
  208. onChanged: (value) {
  209. controller.data.setBeauty(value.toInt());
  210. setState(() {
  211. this.value = value;
  212. });
  213. }),
  214. ),
  215. ],
  216. );
  217. }
  218. return Container();
  219. },
  220. ),
  221. ],
  222. ),
  223. );
  224. }
  225. }