yourinrolltoolsstream 1.1.3 copy "yourinrolltoolsstream: ^1.1.3" to clipboard
yourinrolltoolsstream: ^1.1.3 copied to clipboard

outdated

Camera control on Android and iOS. record video, take pictures, and also support rtmp streaming. Based on the camera plugin for the Youinroll Flutter social network community.

example/lib/main.dart

// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// ignore_for_file: public_member_api_docs

import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:crypto/crypto.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:http/http.dart';
import 'package:yourinrolltoolsstream/camera.dart';
import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';
import 'package:wakelock/wakelock.dart';
import 'package:web_socket_channel/web_socket_channel.dart';

// class CameraExampleHome extends StatefulWidget {
//   @override
//   _CameraExampleHomeState createState() {
//     return _CameraExampleHomeState();
//   }
// }

// class _CameraExampleHomeState extends State<CameraExampleHome>
//     with WidgetsBindingObserver {
//   CameraController controller;
//   String imagePath;
//   String videoPath;
//   String url;
//   VideoPlayerController videoController;
//   VoidCallback videoPlayerListener;
//   bool enableAudio = true;
//   bool useOpenGL = true;
//   TextEditingController _textFieldController =
//       TextEditingController(text: "rtmp://192.168.68.116/live/your_stream");
//
//   bool get isStreaming => controller?.value?.isStreamingVideoRtmp ?? false;
//   bool isVisible = true;
//
//   @override
//   void initState() {
//     super.initState();
//     WidgetsBinding.instance.addObserver(this);
//   }
//
//   @override
//   void dispose() {
//     WidgetsBinding.instance.removeObserver(this);
//     Wakelock.disable();
//     super.dispose();
//   }
//
//   @override
//   Future<void> didChangeAppLifecycleState(AppLifecycleState state) async {
//     // App state changed before we got the chance to initialize.
//     if (controller == null || !controller.value.isInitialized) {
//       return;
//     }
//     if (state == AppLifecycleState.paused) {
//       isVisible = false;
//       if(isStreaming) {
//         await pauseVideoStreaming();
//       }
//     } else if (state == AppLifecycleState.resumed) {
//       isVisible = true;
//       if (controller != null) {
//         if(isStreaming) {
//           await resumeVideoStreaming();
//         } else {
//           onNewCameraSelected(controller.description);
//         }
//
//       }
//     }
//   }
//
//   final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
//   ////////////var showSnackBar;
//   //(){
//
//  // }
//
//   @override
//   Widget build(BuildContext context) {
//     return Scaffold(
//       key: _scaffoldKey,
//       appBar: AppBar(
//         title: const Text('Camera example'),
//       ),
//       body: Column(
//         children: <Widget>[
//           Expanded(
//             child: Container(
//               child: Padding(
//                 padding: const EdgeInsets.all(1.0),
//                 child: Center(
//                   child: _cameraPreviewWidget(),
//                 ),
//               ),
//               decoration: BoxDecoration(
//                 color: Colors.black,
//                 border: Border.all(
//                   color: controller != null && controller.value.isRecordingVideo
//                       ? controller.value.isStreamingVideoRtmp
//                           ? Colors.redAccent
//                           : Colors.orangeAccent
//                       : controller != null &&
//                               controller.value.isStreamingVideoRtmp
//                           ? Colors.blueAccent
//                           : Colors.grey,
//                   width: 3.0,
//                 ),
//               ),
//             ),
//           ),
//           _captureControlRowWidget(),
//           _toggleAudioWidget(),
//           Padding(
//             padding: const EdgeInsets.all(5.0),
//             child: Row(
//               mainAxisAlignment: MainAxisAlignment.start,
//               children: <Widget>[
//                 _cameraTogglesRowWidget(),
//                 _thumbnailWidget(),
//               ],
//             ),
//           ),
//         ],
//       ),
//     );
//   }
//
//   /// Display the preview from the camera (or a message if the preview is not available).
//   Widget _cameraPreviewWidget() {
//     if (controller == null || !controller.value.isInitialized) {
//       return const Text(
//         'Tap a camera',
//         style: TextStyle(
//           color: Colors.white,
//           fontSize: 24.0,
//           fontWeight: FontWeight.w900,
//         ),
//       );
//     } else {
//       return AspectRatio(
//         aspectRatio: controller.value.aspectRatio,
//         child: CameraPreview(controller),
//       );
//     }
//   }
//
//   /// Toggle recording audio
//   Widget _toggleAudioWidget() {
//     return Padding(
//       padding: const EdgeInsets.only(left: 25),
//       child: Row(
//         children: <Widget>[
//           const Text('Enable Audio:'),
//           Switch(
//             value: enableAudio,
//             onChanged: (bool value) {
//               enableAudio = value;
//               if (controller != null) {
//                 onNewCameraSelected(controller.description);
//               }
//             },
//           ),
//         ],
//       ),
//     );
//   }
//
//   /// Display the thumbnail of the captured image or video.
//   Widget _thumbnailWidget() {
//     return Expanded(
//       child: Align(
//         alignment: Alignment.centerRight,
//         child: Row(
//           mainAxisSize: MainAxisSize.min,
//           children: <Widget>[
//             videoController == null && imagePath == null
//                 ? Container()
//                 : SizedBox(
//                     child: (videoController == null)
//                         ? Image.file(File(imagePath))
//                         : Container(
//                             child: Center(
//                               child: AspectRatio(
//                                   aspectRatio:
//                                       videoController.value.size != null
//                                           ? videoController.value.aspectRatio
//                                           : 1.0,
//                                   child: VideoPlayer(videoController)),
//                             ),
//                             decoration: BoxDecoration(
//                                 border: Border.all(color: Colors.pink)),
//                           ),
//                     width: 64.0,
//                     height: 64.0,
//                   ),
//           ],
//         ),
//       ),
//     );
//   }
//
//   /// Display the control bar with buttons to take pictures and record videos.
//   Widget _captureControlRowWidget() {
//     return Row(
//       mainAxisAlignment: MainAxisAlignment.spaceEvenly,
//       mainAxisSize: MainAxisSize.max,
//       children: <Widget>[
//         IconButton(
//           icon: const Icon(Icons.camera_alt),
//           color: Colors.blue,
//           onPressed: controller != null && controller.value.isInitialized
//               ? onTakePictureButtonPressed
//               : null,
//         ),
//         IconButton(
//           icon: const Icon(Icons.videocam),
//           color: Colors.blue,
//           onPressed: controller != null &&
//                   controller.value.isInitialized &&
//                   !controller.value.isRecordingVideo
//               ? onVideoRecordButtonPressed
//               : null,
//         ),
//         IconButton(
//           icon: const Icon(Icons.watch),
//           color: Colors.blue,
//           onPressed: controller != null &&
//                   controller.value.isInitialized &&
//                   !controller.value.isStreamingVideoRtmp
//               ? onVideoStreamingButtonPressed
//               : null,
//         ),
//         IconButton(
//           icon: controller != null &&
//                   (controller.value.isRecordingPaused ||
//                       controller.value.isStreamingPaused)
//               ? Icon(Icons.play_arrow)
//               : Icon(Icons.pause),
//           color: Colors.blue,
//           onPressed: controller != null &&
//                   controller.value.isInitialized &&
//                   (controller.value.isRecordingVideo ||
//                       controller.value.isStreamingVideoRtmp)
//               ? (controller != null &&
//                       (controller.value.isRecordingPaused ||
//                           controller.value.isStreamingPaused)
//                   ? onResumeButtonPressed
//                   : onPauseButtonPressed)
//               : null,
//         ),
//         IconButton(
//           icon: const Icon(Icons.stop),
//           color: Colors.red,
//           onPressed: controller != null &&
//                   controller.value.isInitialized &&
//                   (controller.value.isRecordingVideo ||
//                       controller.value.isStreamingVideoRtmp)
//               ? onStopButtonPressed
//               : null,
//         )
//       ],
//     );
//   }
//
//   /// Display a row of toggle to select the camera (or a message if no camera is available).
//   Widget _cameraTogglesRowWidget() {
//     final List<Widget> toggles = <Widget>[];
//
//     if (cameras.isEmpty) {
//       return const Text('No camera found');
//     } else {
//       for (CameraDescription cameraDescription in cameras) {
//         toggles.add(
//           SizedBox(
//             width: 90.0,
//             child: RadioListTile<CameraDescription>(
//               title: Icon(getCameraLensIcon(cameraDescription.lensDirection)),
//               groupValue: controller?.description,
//               value: cameraDescription,
//               onChanged: controller != null && controller.value.isRecordingVideo
//                   ? null
//                   : onNewCameraSelected,
//             ),
//           ),
//         );
//       }
//     }
//
//     return Row(children: toggles);
//   }
//   //final _scaffoldKey = GlobalKey<ScaffoldState>();
//   String timestamp() => DateTime.now().millisecondsSinceEpoch.toString();
//
//   void showInSnackBar(String message) {
//     // ignore: deprecated_member_use
//    ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(message)));
//   }
// //  showSnackBar(){
//
//  // }
//
//   void onNewCameraSelected(CameraDescription cameraDescription) async {
//     if (controller != null) {
//       await stopVideoStreaming();
//       await controller.dispose();
//     }
//     controller = CameraController(
//       cameraDescription,
//       ResolutionPreset.medium,
//       enableAudio: enableAudio,
//       androidUseOpenGL: useOpenGL,
//     );
//
//     // If the controller is updated then update the UI.
//     controller.addListener(() async {
//       if (mounted) setState(() {});
//       if (controller.value.hasError) {
//         showInSnackBar('Camera error ${controller.value.errorDescription}');
//         await stopVideoStreaming();
//       } else {
//         try {
//           final Map<dynamic, dynamic> event =
//           controller.value.event as Map<dynamic, dynamic>;
//           if (event != null) {
//             print('Event $event');
//             final String eventType = event['eventType'] as String;
//             if (isVisible && isStreaming && eventType == 'rtmp_retry') {
//               showInSnackBar('BadName received, endpoint in use.');
//               await stopVideoStreaming();
//             }
//           }
//         } catch (e) {
//           print(e);
//         }
//       }
//     });
//
//     try {
//       await controller.initialize();
//     } on CameraException catch (e) {
//       _showCameraException(e);
//     }
//
//     if (mounted) {
//       setState(() {});
//     }
//   }
//
//   void onTakePictureButtonPressed() {
//     takePicture().then((String filePath) {
//       if (mounted) {
//         setState(() {
//           imagePath = filePath;
//           videoController?.dispose();
//           videoController = null;
//         });
//         if (filePath != null) showInSnackBar('Picture saved to $filePath');
//       }
//     });
//   }
//
//   void onVideoRecordButtonPressed() {
//     startVideoRecording().then((String filePath) {
//       if (mounted) setState(() {});
//       if (filePath != null) showInSnackBar('Saving video to $filePath');
//       Wakelock.enable();
//     });
//   }
//
//   void onVideoStreamingButtonPressed() {
//     startVideoStreaming().then((String url) {
//       if (mounted) setState(() {});
//       if (url != null) showInSnackBar('Streaming video to $url');
//       Wakelock.enable();
//     });
//   }
//
//   void onRecordingAndVideoStreamingButtonPressed() {
//     startRecordingAndVideoStreaming().then((String url) {
//       if (mounted) setState(() {});
//       if (url != null) showInSnackBar('Recording streaming video to $url');
//       Wakelock.enable();
//     });
//   }
//
//   void onStopButtonPressed() {
//     if (this.controller.value.isStreamingVideoRtmp) {
//       stopVideoStreaming().then((_) {
//         if (mounted) setState(() {});
//         showInSnackBar('Video streamed to: $url');
//       });
//     } else {
//       stopVideoRecording().then((_) {
//         if (mounted) setState(() {});
//         showInSnackBar('Video recorded to: $videoPath');
//       });
//     }
//     Wakelock.disable();
//   }
//
//   void onPauseButtonPressed() {
//     pauseVideoRecording().then((_) {
//       if (mounted) setState(() {});
//       showInSnackBar('Video recording paused');
//     });
//   }
//
//   void onResumeButtonPressed() {
//     resumeVideoRecording().then((_) {
//       if (mounted) setState(() {});
//       showInSnackBar('Video recording resumed');
//     });
//   }
//
//   void onStopStreamingButtonPressed() {
//     stopVideoStreaming().then((_) {
//       if (mounted) setState(() {});
//       showInSnackBar('Video not streaming to: $url');
//     });
//   }
//
//   void onPauseStreamingButtonPressed() {
//     pauseVideoStreaming().then((_) {
//       if (mounted) setState(() {});
//       showInSnackBar('Video streaming paused');
//     });
//   }
//
//   void onResumeStreamingButtonPressed() {
//     resumeVideoStreaming().then((_) {
//       if (mounted) setState(() {});
//       showInSnackBar('Video streaming resumed');
//     });
//   }
//
//   Future<String> startVideoRecording() async {
//     if (!controller.value.isInitialized) {
//       showInSnackBar('Error: select a camera first.');
//       return null;
//     }
//
//     final Directory extDir = await getExternalStorageDirectory();
//     final String dirPath = '${extDir.path}/Movies/flutter_test';
//     await Directory(dirPath).create(recursive: true);
//     final String filePath = '$dirPath/${timestamp()}.mp4';
//
//     if (controller.value.isRecordingVideo) {
//       // A recording is already started, do nothing.
//       return null;
//     }
//
//     try {
//       videoPath = filePath;
//       await controller.startVideoRecording(filePath);
//     } on CameraException catch (e) {
//       _showCameraException(e);
//       return null;
//     }
//     return filePath;
//   }
//
//   Future<void> stopVideoRecording() async {
//     if (!controller.value.isRecordingVideo) {
//       return null;
//     }
//
//     try {
//       await controller.stopVideoRecording();
//     } on CameraException catch (e) {
//       _showCameraException(e);
//       return null;
//     }
//
//     await _startVideoPlayer();
//   }
//
//   Future<void> pauseVideoRecording() async {
//     try {
//       if (controller.value.isRecordingVideo) {
//         await controller.pauseVideoRecording();
//       }
//       if (controller.value.isStreamingVideoRtmp) {
//         await controller.pauseVideoStreaming();
//       }
//     } on CameraException catch (e) {
//       _showCameraException(e);
//       rethrow;
//     }
//   }
//
//   Future<void> resumeVideoRecording() async {
//     try {
//       if (controller.value.isRecordingVideo) {
//         await controller.resumeVideoRecording();
//       }
//       if (controller.value.isStreamingVideoRtmp) {
//         await controller.resumeVideoStreaming();
//       }
//     } on CameraException catch (e) {
//       _showCameraException(e);
//       rethrow;
//     }
//   }
//
//   Future<String> _getUrl() async {
//     // Open up a dialog for the url
//     String result = _textFieldController.text;
//
//     return await showDialog(
//         context: context,
//         builder: (context) {
//           return AlertDialog(
//             title: Text('Url to Stream to'),
//             content: TextField(
//               controller: _textFieldController,
//               decoration: InputDecoration(hintText: "Url to Stream to"),
//               onChanged: (String str) => result = str,
//             ),
//             actions: <Widget>[
//               // ignore: deprecated_member_use
//               new TextButton(
//                 child: new Text(
//                     MaterialLocalizations.of(context).cancelButtonLabel),
//                 onPressed: () {
//                   Navigator.of(context).pop();
//                 },
//               ),
//               // ignore: deprecated_member_use
//               TextButton(
//                 child: Text(MaterialLocalizations.of(context).okButtonLabel),
//                 onPressed: () {
//                   Navigator.pop(context, result);
//                 },
//               )
//             ],
//           );
//         });
//   }
//
//   Future<String> startRecordingAndVideoStreaming() async {
//     if (!controller.value.isInitialized) {
//       showInSnackBar('Error: select a camera first.');
//       return null;
//     }
//
//     if (controller.value.isStreamingVideoRtmp ||
//         controller.value.isStreamingVideoRtmp) {
//       return null;
//     }
//
//     String myUrl = await _getUrl();
//
//     final Directory extDir = await getApplicationDocumentsDirectory();
//     final String dirPath = '${extDir.path}/Movies/flutter_test';
//     await Directory(dirPath).create(recursive: true);
//     final String filePath = '$dirPath/${timestamp()}.mp4';
//
//     try {
//       url = myUrl;
//       videoPath = filePath;
//       await controller.startVideoRecordingAndStreaming(videoPath, url);
//     } on CameraException catch (e) {
//       _showCameraException(e);
//       return null;
//     }
//     return url;
//   }
//
//   Future<String> startVideoStreaming() async {
//     await stopVideoStreaming();
//     if (controller == null) {
//       return null;
//     }
//     if (!controller.value.isInitialized) {
//       showInSnackBar('Error: select a camera first.');
//       return null;
//     }
//
//     if (controller?.value?.isStreamingVideoRtmp ?? false) {
//       return null;
//     }
//
//     // Open up a dialog for the url
//     String myUrl = await _getUrl();
//
//     try {
//       url = myUrl;
//       await controller.startVideoStreaming(url);
//     } on CameraException catch (e) {
//       _showCameraException(e);
//       return null;
//     }
//     return url;
//   }
//
//   Future<void> stopVideoStreaming() async {
//
//     if (controller == null || !controller.value.isInitialized) {
//       return;
//     }
//     if (!controller.value.isStreamingVideoRtmp) {
//       return;
//     }
//
//     try {
//       await controller.stopVideoStreaming();
//     } on CameraException catch (e) {
//       _showCameraException(e);
//       return null;
//     }
//   }
//
//   Future<void> pauseVideoStreaming() async {
//     if (!controller.value.isStreamingVideoRtmp) {
//       return null;
//     }
//
//     try {
//       await controller.pauseVideoStreaming();
//     } on CameraException catch (e) {
//       _showCameraException(e);
//       rethrow;
//     }
//   }
//
//   Future<void> resumeVideoStreaming() async {
//     if (!controller.value.isStreamingVideoRtmp) {
//       return null;
//     }
//
//     try {
//       await controller.resumeVideoStreaming();
//     } on CameraException catch (e) {
//       _showCameraException(e);
//       rethrow;
//     }
//   }
//
//   Future<void> _startVideoPlayer() async {
//     final VideoPlayerController vcontroller =
//         VideoPlayerController.file(File(videoPath));
//     videoPlayerListener = () {
//       if (videoController != null && videoController.value.size != null) {
//         // Refreshing the state to update video player with the correct ratio.
//         if (mounted) setState(() {});
//         videoController.removeListener(videoPlayerListener);
//       }
//     };
//     vcontroller.addListener(videoPlayerListener);
//     await vcontroller.setLooping(true);
//     await vcontroller.initialize();
//     await videoController?.dispose();
//     if (mounted) {
//       setState(() {
//         imagePath = null;
//         videoController = vcontroller;
//       });
//     }
//     await vcontroller.play();
//   }
//
//   Future<String> takePicture() async {
//     if (!controller.value.isInitialized) {
//       showInSnackBar('Error: select a camera first.');
//       return null;
//     }
//     final Directory extDir = await getExternalStorageDirectory();
//     final String dirPath = '${extDir.path}/Pictures/flutter_test';
//     await Directory(dirPath).create(recursive: true);
//     final String filePath = '$dirPath/${timestamp()}.jpg';
//
//     if (controller.value.isTakingPicture) {
//       // A capture is already pending, do nothing.
//       return null;
//     }
//
//     try {
//       await controller.takePicture(filePath);
//     } on CameraException catch (e) {
//       _showCameraException(e);
//       return null;
//     }
//     return filePath;
//   }
//
//   void _showCameraException(CameraException e) {
//     logError(e.code, e.description);
//     showInSnackBar('Error: ${e.code}\n${e.description}');
//   }
// }

/// Returns a suitable camera icon for [direction].
IconData getCameraLensIcon(CameraLensDirection direction) {
  switch (direction) {
    case CameraLensDirection.back:
      return Icons.camera_rear;
    case CameraLensDirection.front:
      return Icons.camera_front;
    case CameraLensDirection.external:
      return Icons.camera;
  }
}

void logError(String code, String message) =>
    print('Error.: $code\nError Message: $message');

class RtmpVideoStreamPage extends StatefulWidget {
  final int userId;
  final int pageIndex;

  const RtmpVideoStreamPage({
    required this.userId,
    required this.pageIndex,
    super.key,
  });

  @override
  State<RtmpVideoStreamPage> createState() => _RtmpVideoStreamPageState();
}

class _RtmpVideoStreamPageState extends State<RtmpVideoStreamPage> {
  WebSocketChannel? _channel;

  CameraController? controller;
  String? imagePath;
  String? videoPath;
  String? url;

  VideoPlayerController? videoController;
  late VoidCallback videoPlayerListener;

  bool enableAudio = true;
  bool useOpenGL = true;
  String streamURL = "";
  String decodedStreamKey = '';
  bool streaming = false;

  String? cameraDirection;

  late String userName;
  late String dateRegisteredUser;

  Timer? _timer;
  Timer? _timerForCheckBroadcastStatus;

  String? token;
  String? streamId;

  bool isLoaded = false;
  bool broadcastError = false;

  String views = '';

  List<CameraDescription> cameras = [];

  // Future<void> _saveToSharedPrefs(String key, String value) async {
  //   SharedPreferences prefs = await SharedPreferences.getInstance();
  //   prefs.setString(key, value);
  // }

  void getCameras() async {
    await Future.delayed(const Duration(milliseconds: 1))
        .whenComplete(() async {
      try {
        WidgetsFlutterBinding.ensureInitialized();
        cameras = await availableCameras();
        _initialize();
      } on CameraException catch (e) {
        logError(e.code, e.description);
      }
    });
  }

  void checkViews() {
    Map<String, dynamic> myJson = {};

    _channel = WebSocketChannel.connect(
      Uri.parse('ws://35.224.171.186:8081'),
    );
    myJson = {
      'api': 'check_views',
      'stream_id': streamId!,
    };
    _channel?.sink.add(jsonEncode(myJson));
    _channel?.stream.listen((message) {
      if (message != '{}') {
        var jsonData = jsonDecode(message);
        var val = jsonData['viewers'].toString();
        setState(() {
          views = val;
        });
      }
    });
  }

  void getViews() async {
    Uri url = Uri.parse(
        'https://youinroll.com/lib/ajax/conference/getStreamViews.php?stream_id=$streamId');
    Response response = await get(url);

    if (response.statusCode >= 200 && response.statusCode < 400) {
      var jsonResponse = jsonDecode(response.body);
      setState(() {
        views = jsonResponse['result'].toString();
      });
    }
  }

  void getUserToken() async {
    // final prefs = await SharedPreferences.getInstance();
    token =
    '004e6cff74730832deb820d0aee6dd0fc004f5f10ddffe7bb37dc31eceb45e1eeb1b3f14fd5c00e42b575ebbd04fa0bd8d28fdab602f04b80c375aaddd5306ee';
  }

  String generateMd5(String input) {
    return md5.convert(utf8.encode(input)).toString();
  }

  checkBroadcastStatus() async {
    Future.delayed(const Duration(seconds: 20), () {
      _timerForCheckBroadcastStatus =
          Timer.periodic(const Duration(seconds: 10), (_) {
            getBroadcastStatus();
          });
    });
  }

  getBroadcastStatus() async {
    try {
      if (!controller!.value.isStreamingVideoRtmp) {
        showInSnackBar('error, ${controller!.value.isStreamingVideoRtmp}');
        if (streaming) {
          onStopButtonPressed();
        }
        setState(() {
          broadcastError = true;
        });
        _timerForCheckBroadcastStatus?.cancel();
        return;
      }

      Uri url = Uri.parse(
          "https://youinroll.com:8443/hls/${decodedStreamKey}_360p878kbs/index.m3u8");
      Response response = await get(url);
      if (response.statusCode == 404) {
        if (streaming) {
          onStopButtonPressed();
          showInSnackBar('404 code, $url');
        }
        setState(() {
          broadcastError = true;
        });
        _timerForCheckBroadcastStatus?.cancel();
      }
    } catch (e) {
      return;
    }
  }

  @override
  void initState() {
    getCameras();
    getUserToken();
    loadUserData();
    loadUserDataDop();
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.portraitUp,
      DeviceOrientation.portraitDown,
    ]);
    super.initState();
  }

  @override
  void dispose() {
    if (streaming) {
      disposeScreen();
    }
    if (_timerForCheckBroadcastStatus != null) {
      _timerForCheckBroadcastStatus?.cancel();
    }
    if (_channel != null) {
      _channel?.sink.close();
    }
    if (controller != null) {
      controller?.dispose();
    }
    availableCameras().ignore();
    cameras.clear();
    Wakelock.disable();
    super.dispose();
  }

  void loadUserData() async {
    Uri url = Uri.parse(
        'https://youinroll.com/profile/${widget.userId}/info?api=v1.1');
    Response response = await get(url);

    if (response.statusCode == 200) {
      var jsonResponse = jsonDecode(response.body);
      setState(() {
        var userData = jsonResponse['response'];
        var streamKey = userData['chatRoom'].toString();
        userName = userData['name'].toString();
        userAvatar = userData['avatar'].toString();
        userBio = userData['bio'].toString();
        dateRegisteredUser = userData['date_registered'].toString();
        decodedStreamKey = generateMd5(streamKey);
        if (decodedStreamKey.isNotEmpty) {
          // StaticVariables.decodedStreamKey = decodedStreamKey;
          // _saveToSharedPrefs('decodedStreamKey', decodedStreamKey);
        }
        streamURL = "rtmp://youinroll.com:1935/stream/$decodedStreamKey";
      });
    }
  }

  String userFollowers = '';
  String userViews = '';
  String userLikes = '';
  String userAvatar = '';
  String userBio = '';

  void loadUserDataDop() async {
    Uri url = Uri.parse(
        'https://youinroll.com/lib/ajax/getPopularity.php?user_id=${widget.userId}');
    Response response = await get(url);

    if (response.statusCode == 200) {
      var jsonResponse = jsonDecode(response.body);
      userFollowers = jsonResponse['followers'];
      userViews = jsonResponse['views'];
      userLikes = jsonResponse['likes'];
    }
  }

  Future<void> _initialize() async {
    streaming = false;
    cameraDirection = 'front';
    //controller = CameraController(cameras[0], ResolutionPreset.high);
    if (controller != null) {
      await controller?.dispose();
    }
    controller = CameraController(
      cameras[1],
      ResolutionPreset.high,
      enableAudio: enableAudio,
      androidUseOpenGL: useOpenGL,
      streamingPreset: ResolutionPreset.high,
    );
    await controller!.initialize().whenComplete(() {
      if (mounted) {
        setState(() {
          isLoaded = true;
        });
      }
    });
  }

  void didChangeAppLifecycleState(AppLifecycleState state) {
    // App state changed before we got the chance to initialize.
    if (controller == null) {
      return;
    } else if (!controller!.value.isInitialized!) {
      return;
    }
    if (state == AppLifecycleState.inactive) {
      controller?.dispose();
      if (_timer != null) {
        _timer!.cancel();
        _timer = null;
      }
    } else if (state == AppLifecycleState.resumed) {
      if (controller != null) {
        onNewCameraSelected(controller!.description);
      }
    }
  }

  final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();

  toggleCameraDirection() async {
    if (cameraDirection == 'front') {
      if (controller != null) {
        await controller?.dispose();
      }
      controller = CameraController(
        cameras[0],
        ResolutionPreset.high,
        enableAudio: enableAudio,
        androidUseOpenGL: useOpenGL,
      );

      // If the controller is updated then update the UI.
      controller!.addListener(() {
        if (mounted) setState(() {});
        if (controller!.value.hasError) {
          showInSnackBar('Camera error ${controller!.value.errorDescription}');
          if (_timer != null) {
            _timer!.cancel();
            _timer = null;
          }
          if (streaming) {
            // Navigator.pushReplacement(
            //   context,
            //   MaterialPageRoute(
            //     builder: (context) => RootApp(
            //       pageIndex: widget.pageIndex,
            //     ),
            //   ),
            // );
          }
        }
      });

      try {
        await controller!.initialize();
      } on CameraException catch (e) {
        _showCameraException(e);
      }

      if (mounted) {
        setState(() {});
      }
      cameraDirection = 'back';
    } else {
      if (controller != null) {
        await controller!.dispose();
      }
      controller = CameraController(
        cameras[1],
        ResolutionPreset.high,
        enableAudio: enableAudio,
        androidUseOpenGL: useOpenGL,
      );

      // If the controller is updated then update the UI.
      controller!.addListener(() {
        if (mounted) setState(() {});
        if (controller!.value.hasError) {
          showInSnackBar('Camera error ${controller!.value.errorDescription}');
          if (_timer != null) {
            _timer!.cancel();
            _timer = null;
          }
          if (streaming) {
            // Navigator.pushReplacement(
            //   context,
            //   MaterialPageRoute(
            //     builder: (context) => RootApp(
            //       pageIndex: widget.pageIndex,
            //     ),
            //   ),
            // );
          }
        }
      });

      try {
        await controller!.initialize();
      } on CameraException catch (e) {
        _showCameraException(e);
      }

      if (mounted) {
        setState(() {});
      }
      cameraDirection = 'front';
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        automaticallyImplyLeading: false,
        backgroundColor: Colors.black.withOpacity(0.5),
        leading: streaming
            ? null
            : IconButton(
          icon: const Icon(
            Icons.settings,
            color: Colors.white,
          ),
          onPressed: () {
            // showDialog(
            //   context: context,
            //   builder: (BuildContext context) {
            //     return Dialog(
            //       shape: RoundedRectangleBorder(
            //         borderRadius: BorderRadius.circular(20.0),
            //       ),
            //       child: Container(
            //         constraints: const BoxConstraints(maxHeight: 500),
            //         child: SettingBroadcastModal(
            //           token: token!,
            //         ),
            //       ),
            //     );
            //   },
            // );
          },
        ),
        actions: [
          IconButton(
              onPressed: () {
                if (streaming) {
                  delStream();
                }
                // Navigator.pushReplacement(
                //   context,
                //   MaterialPageRoute(
                //     builder: (context) => RootApp(
                //       pageIndex: widget.pageIndex,
                //     ),
                //   ),
                // );

              },
              icon: const Icon(Icons.close)),
        ],
      ),
      extendBodyBehindAppBar: true,
      resizeToAvoidBottomInset: true,
      key: _scaffoldKey,
      body: WillPopScope(
        onWillPop: () async => false,
        child: SingleChildScrollView(
          child: broadcastError
              ? _broadcastErrorWidget()
              : SizedBox(
            height: MediaQuery.of(context).size.height,
            child: Stack(
              children: <Widget>[
                Container(
                  color: Colors.black,
                  child: Center(
                    child: _cameraPreviewWidget(),
                  ),
                ),
                // if(streaming)
                //
                !streaming
                    ? Align(
                  alignment: Alignment.bottomRight,
                  child: Padding(
                    padding: const EdgeInsets.only(
                        bottom: 90, right: 20),
                    child: IconButton(
                      color: Colors.white38.withOpacity(0.3),
                      icon: const Icon(Icons.flip_camera_android),
                      alignment: Alignment.topRight,
                      iconSize: 40.0,
                      // tooltip: switchCameraTr.trText,
                      onPressed: () {
                        toggleCameraDirection();
                      },
                    ),
                  ),
                )
                    : Align(
                  alignment: Alignment.topRight,
                  child: Container(
                    padding:
                    const EdgeInsets.only(top: 120, right: 20),
                    child: Row(
                        mainAxisAlignment: MainAxisAlignment.end,
                        crossAxisAlignment:
                        CrossAxisAlignment.center,
                        children: [
                          Padding(
                            padding:
                            const EdgeInsets.only(right: 5),
                            child: Container(
                              padding: const EdgeInsets.only(
                                  right: 7, left: 7),
                              decoration: const BoxDecoration(
                                color: Color(0xFFFE2C55),
                                borderRadius: BorderRadius.all(
                                    Radius.circular(6.0)),
                              ),
                              child: Text(
                                // liveTr.trText,
                                'LIVE',
                                style: const TextStyle(
                                  color: Colors.white,
                                  fontSize: 16,
                                ),
                              ),
                            ),
                          ),
                          const Icon(
                            // TTkIcons.profile,
                            Icons.people,
                            color: Colors.white,
                          ),
                          Text(
                            views,
                            style: const TextStyle(
                              color: Colors.white,
                              fontWeight: FontWeight.w400,
                              fontSize: 24,
                            ),
                          ),
                        ]),
                  ),
                ),
                streaming
                    ? Align(
                  alignment: Alignment.bottomRight,
                  child: Padding(
                      padding: const EdgeInsets.only(
                          bottom: 60, right: 20),
                      child: RawMaterialButton(
                        onPressed: () {
                          // Vibration.vibrate(
                          //   duration: 200,
                          //   amplitude: 1,
                          // );
                          onStopButtonPressed();
                        },
                        elevation: 2.0,
                        fillColor: const Color(0xFFFE2C55),
                        padding: const EdgeInsets.all(15.0),
                        shape: const CircleBorder(),
                        //Colors.white.withAlpha(60),
                        child: const Icon(
                          Icons.stop,
                          size: 35.0,
                          color: Colors.white,
                        ),
                      )),
                )
                    : Align(
                  alignment: Alignment.center,
                  child: isLoaded
                      ? RawMaterialButton(
                    onPressed: () {
                      // Vibration.vibrate(
                      //   duration: 200,
                      //   amplitude: 1,
                      // );
                      onVideoStreamingButtonPressed();
                    },
                    elevation: 2.0,
                    fillColor: const Color(0xFFFE2C55),
                    padding: const EdgeInsets.all(15.0),
                    shape: const CircleBorder(),
                    //Colors.white.withAlpha(60),
                    child: const Icon(
                      Icons.play_arrow,
                      size: 35.0,
                      color: Colors.white,
                    ),
                  )
                      : const CupertinoActivityIndicator(),
                ),
                streaming
                    ? Align(
                  alignment: Alignment.bottomLeft,
                  child: Container(
                    padding: const EdgeInsets.only(bottom: 20),
                    width: 280,
                    height: 400,
                    color: Colors.transparent,
                    child: Container(),
                    // child: StreamChat(
                    //   user_id: widget.userId.toString(),
                    //   user_name: userName,
                    //   date_registered_user: dateRegisteredUser,
                    //   token: token!,
                    //   streamId: streamId!,
                    //   followers: userFollowers,
                    //   views: userViews,
                    //   likes: userLikes,
                    //   user_avatar: userAvatar,
                    //   userBio: userBio,
                    //   isBroadcastCreator: true,
                    // ),
                  ),
                )
                    : const SizedBox(),
                streaming
                    ? const SizedBox()
                    : Align(
                  alignment: Alignment.bottomCenter,
                  child: Padding(
                    padding: const EdgeInsets.only(bottom: 20),
                    child: SizedBox(
                      height: 50,
                      child: Row(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: [
                          InkWell(
                            onTap: () {
                              if (controller != null) {
                                controller?.dispose();
                              }
                              // Vibration.vibrate(
                              //   duration: 200,
                              //   amplitude: 1,
                              // );
                              // Navigator.pushReplacement(
                              //   context,
                              //   MaterialPageRoute(
                              //     builder: (context) =>
                              //         PostScreenFromGallery(
                              //       userId: widget.userId,
                              //       myPageIndex: widget.pageIndex,
                              //     ),
                              //   ),
                              // );
                            },
                            child: Text(
                              // kpostTr.trText,
                              'POST',
                              style: const TextStyle(
                                  color: Colors.white70,
                                  fontSize: 20,
                                  fontWeight: FontWeight.w400),
                            ),
                          ),
                          const SizedBox(width: 20),
                          Text(
                            // liveTr.trText,
                            'LIVE',
                            style: const TextStyle(
                                color: Colors.white,
                                fontSize: 20,
                                fontWeight: FontWeight.w500),
                          ),
                          const SizedBox(width: 20),
                          InkWell(
                            onTap: () {
                              if (controller != null) {
                                controller?.dispose();
                              }
                              // Vibration.vibrate(
                              //   duration: 200,
                              //   amplitude: 1,
                              // );
                              ScaffoldMessenger.of(context)
                                  .showSnackBar(
                                const SnackBar(
                                  content: Text(
                                    'Here was push to GetVideoPage',
                                  ),
                                ),
                              );
                              // Navigator.pushReplacement(
                              //   context,
                              //   MaterialPageRoute(
                              //     builder: (context) =>
                              //         GetVideoPage(
                              //       user_id: widget.user_id,
                              //       myPageIndex: widget.page_index,
                              //       userHasStream: true,
                              //     ),
                              //   ),
                              // );
                            },
                            child: Text(
                              // cameraTr.trText,
                              'CAMERA',
                              style: Theme.of(context)
                                  .textTheme
                                  .bodyText2
                                  ?.copyWith(
                                  color: Colors.white70,
                                  fontSize: 20,
                                  fontWeight: FontWeight.w400),
                            ),
                          ),
                        ],
                      ),
                    ),
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }

  Widget _broadcastErrorWidget() {
    return SizedBox(
      height: MediaQuery.of(context).size.height,
      child: Stack(
        children: [
          // Blur(
          //   colorOpacity: 0.85,
          //   blur: 30,
          //   blurColor: Colors.black,
          //   child: Container(
          //     color: Colors.black,
          //     child: Center(
          //       child: _cameraPreviewWidget(),
          //     ),
          //   ),
          // ),
          Center(
            child: RawMaterialButton(
              onPressed: () {
                // Vibration.vibrate(
                //   duration: 200,
                //   amplitude: 1,
                // );
                onVideoStreamingButtonPressed();
                setState(() {
                  broadcastError = false;
                  streaming = true;
                });
              },
              elevation: 2.0,
              fillColor: const Color(0xFFFE2C55),
              padding: const EdgeInsets.all(15.0),
              shape: const CircleBorder(),
              child: const Icon(
                Icons.autorenew,
                size: 35.0,
                color: Colors.white,
              ),
            ),
          ),
        ],
      ),
    );
  }

  /// Display the preview from the camera (or a message if the preview is not available).
  Widget _cameraPreviewWidget() {
    if (controller == null) {
      return const CupertinoActivityIndicator();
    } else if (!controller!.value.isInitialized!) {
      return const CupertinoActivityIndicator();
    } else {
      if (isLoaded) {
        return AspectRatio(
          aspectRatio: controller!.value.aspectRatio,
          // aspectRatio: size.height / size.width,
          child: CameraPreview(controller!),
        );
      } else {
        return const CupertinoActivityIndicator();
      }
    }
  }

  String timestamp() => DateTime.now().millisecondsSinceEpoch.toString();

  void showInSnackBar(String message) {
    ScaffoldMessenger.of(context)
        .showSnackBar(SnackBar(content: Text(message)));
  }

  void onNewCameraSelected(CameraDescription? cameraDescription) async {
    if (controller != null) {
      await controller!.dispose();
    }
    controller = CameraController(
      cameraDescription!,
      ResolutionPreset.medium,
      enableAudio: enableAudio,
      androidUseOpenGL: useOpenGL,
    );

    // If the controller is updated then update the UI.
    controller!.addListener(() {
      if (mounted) setState(() {});
      if (controller!.value.hasError) {
        showInSnackBar('CAMERA ERROR: ${controller!.value.errorDescription}');
        if (_timer != null) {
          _timer!.cancel();
          _timer = null;
        }
        Wakelock.disable();
      }
    });

    try {
      await controller!.initialize();
    } on CameraException catch (e) {
      _showCameraException(e);
    }

    if (mounted) {
      setState(() {});
    }
  }

  void onVideoStreamingButtonPressed() {
    startVideoStreaming().then((url) {
      if (mounted) {
        setState(() {
          // streaming = true;
        });
      }
    });
    pushStream();
    Wakelock.enable();
  }

  void onStopButtonPressed() {
    _timerForCheckBroadcastStatus?.cancel();
    stopVideoStreaming().then((_) {
      showInSnackBar(
        // broadcastSavedTr.trText,
        'Broadcast saved',
      );
    });
    try {
      delStream();
    } catch (e) {
      if (kDebugMode) {
        print(e);
      }
    }
    Wakelock.disable();
  }

  void onPauseStreamingButtonPressed() {
    pauseVideoStreaming().then(
          (_) {
        if (mounted) setState(() {});
        showInSnackBar(
          // streamingPausedTr.trText,
          'Streaming paused',
        );
      },
    );
  }

  void onResumeStreamingButtonPressed() {
    resumeVideoStreaming().then((_) {
      if (mounted) setState(() {});
      showInSnackBar(
        'Streaming resumed',
      );
    });
  }

  Future<String?> startVideoStreaming() async {
    if (!controller!.value.isInitialized!) {
      showInSnackBar(
        'Camera error message',
      );
      return null;
    }

    // Open up a dialog for the url
    String myUrl = streamURL;

    try {
      if (_timer != null) {
        _timer!.cancel();
        _timer = null;
      }
      url = myUrl;
      int wid = MediaQuery.of(context).size.width.round();
      int hei = MediaQuery.of(context).size.height.round();
      if (!wid.isEven) {
        wid++;
      }
      if (!hei.isEven) {
        hei++;
      }
      String a = '${url!}?${hei}x$wid';
      await controller!.startVideoStreaming(a, androidUseOpenGL: useOpenGL);
      checkBroadcastStatus();
    } on CameraException catch (e) {
      _showCameraException(e);
      if (streaming) {
        delStream();
      }
      // Navigator.pushReplacement(
      //   context,
      //   MaterialPageRoute(
      //     builder: (context) => RootApp(
      //       pageIndex: widget.pageIndex,
      //     ),
      //   ),
      // );
      return null;
    }
    return url;
  }

  Future<void> stopVideoStreaming() async {
    try {
      await controller!.stopVideoStreaming();
      if (_timer != null) {
        _timer!.cancel();
        _timer = null;
      }
    } on CameraException catch (e, s) {
      print('EXCEPTION OCCURRED: $e');
      print('TRACE: $s');
      _showCameraException(e);
      return;
    }
  }

  Future<void> pauseVideoStreaming() async {
    if (!controller!.value.isStreamingVideoRtmp) {
      return;
    }
    try {
      await controller!.pauseVideoStreaming();
    } on CameraException catch (e) {
      _showCameraException(e);
      rethrow;
    }
  }

  Future<void> resumeVideoStreaming() async {
    try {
      await controller!.resumeVideoStreaming();
    } on CameraException catch (e) {
      _showCameraException(e);
      rethrow;
    }
  }

  void _showCameraException(CameraException e) {
    try {
      logError(e.code, e.description);
      showInSnackBar('Error: ${e.code}\n${e.description}');
    } catch (e) {
      return;
    }
  }

  void pushStream() async {
    bool isFrontCam = false;
    if (cameraDirection == 'front') {
      isFrontCam = true;
    }
    var padding = MediaQuery.of(context).padding;
    double height =
        MediaQuery.of(context).size.height - padding.top - padding.bottom;
    String os = Platform.operatingSystem;
    Uri url =
    Uri.parse('https://youinroll.com/lib/ajax/conference/beginStream.php');
    Response response = await post(url, body: {
      'token': token,
      'platform': os,
      'height': height.toString(),
      'width': MediaQuery.of(context).size.width.toString(),
      'is_front_camera': isFrontCam ? '1' : '0',
    });

    if (response.statusCode >= 200 && response.statusCode < 400) {
      var jsonData = jsonDecode(response.body);
      streamId = jsonData['stream_id'].toString();
      getViews();
      checkViews();
      setState(() {
        streaming = true;
      });
    }
  }

  void delStream() async {
    Uri url =
    Uri.parse('https://youinroll.com/lib/ajax/conference/stopStream.php');
    await post(url, body: {
      'token': token,
    });
    if (mounted) {
      setState(() {
        streaming = false;
      });
    }
  }

  void disposeScreen() async {
    if (controller!.value.isInitialized!) {
      await controller?.stopVideoStreaming();
    }
    if (controller != null) {
      controller?.dispose();
    }
    Uri url =
    Uri.parse('https://youinroll.com/lib/ajax/conference/stopStream.php');
    await post(url, body: {
      'token': token,
    });
  }
}

class CameraApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: RtmpVideoStreamPage(
        userId: 3310,
        pageIndex: 1,
      ),
    );
  }
}

List<CameraDescription> cameras = [];

Future<void> main() async {
  // Fetch the available cameras before initializing the app.
  try {
    WidgetsFlutterBinding.ensureInitialized();
    cameras = await availableCameras();
  } on CameraException catch (e) {
    logError(e.code, e.description);
  }
  runApp(CameraApp());
}
2
likes
0
pub points
0%
popularity

Publisher

verified publisheryouinroll.com

Camera control on Android and iOS. record video, take pictures, and also support rtmp streaming. Based on the camera plugin for the Youinroll Flutter social network community.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

crypto, flutter, http, rename, web_socket_channel

More

Packages that depend on yourinrolltoolsstream