Recording Video (Pause/Resume)

Hi there

I’ve been able to record video with simple examples that I’ve found from various sources on the internet but what I cannot find/achieve is the ability to record video while a user holds down a button on the screen, which then stops recording when the button is no longer held down and then continues recording when the button is held again.

The closest I have gotten is to be able to do the first part of the functionality, where you can hold the button to record but once the button is released a video file is created. I’ve tried combining multiple files into a single video file to no avail.

Does anyone have any info on how to go about achieving this?

Thanks.

1 Like

What determines when a video is finished recoding?
For ex:

  1. User holds the button, the recording starts.
  2. User leaves the button, recording finishes.
  3. User holds the button again, recording continues.

What is the trigger to finish / stop recording?

1 Like

There will be a separate button which will allow the user to accept/complete the recording (see attached image).

The plan is to have an upper limit [eg] 30 seconds max recording time in total.
User presses and holds the record button and video is recorded while button is held.
If the user takes their finger off the record button then recording is stopped.
If user presses and holds record button again the recording is resumed.
The user can stop/resume the recording of video as many times as they wish or until the upper limit is reached.
The user can press the replay button to view all parts of recorded video as a single combined video.
The user can press the accept button which will continue on to the rest of the app.

3 Likes

Really appreciate your detailed explanation, it helped me to construct the solution.

Personally I don’t have hands on experience when it comes to recording video from camera package, this is the first time I am giving this a try. The solution that I have come up with is going through the package’s example code and documentation.

As far as I could understand, I have come up with a working solution.
The UI is different as shown in the screenshot below.

There is a ‘View’ button on top left, I have used video_player example code, which I tweaked to play the recorded video. I will not be uploading video player code. As it is exactly the same code as example code from video_player package.

Packages used:
 camera: ^0.5.7+2
 video_player: ^0.10.5+1
 path_provider: ^1.5.1

I have included enough logging to get a good understanding of the logic and the solution.

I repeat again, it is not exactly as you might have expected but the core logic is implemented, which can be extended to fit your use case.

Please let me know if you have any further questions and if this was helpful.

main.dart

import 'package:flutter/material.dart';
import 'package:camera/camera.dart';

import './cam_renderer.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Video Recorder'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            FloatingActionButton(
              onPressed: () {
                availableCameras().then(
                  (cameras) {
                    print(cameras);
                    CameraController _controller = CameraController(
                      cameras[0],
                      ResolutionPreset.high,
                      enableAudio: true
                    );
                    _controller.initialize().then(
                      (_) {
                        Navigator.push(
                          context, 
                          MaterialPageRoute(
                            builder: (context) => CamRenderer(_controller)
                          )
                        );
                      }                      
                    );
                  }
                );
              },
              child: Icon(Icons.videocam),
            )
          ],
        ),
      ),
    );
  }
}

cam_renderer.dart

import 'package:flutter/material.dart';
import 'dart:io';

import 'package:camera/camera.dart';
import 'package:path_provider/path_provider.dart';

//import './play_video.dart';

class CamRenderer extends StatefulWidget {
  CameraController controller;

  CamRenderer(this.controller);

  @override
  _CamRendererState createState() => _CamRendererState();
}

class _CamRendererState extends State<CamRenderer> {
  String path;
  File filePath;

  int intervalTime = 10; // 30 seconds

  DateTime dateTimeStart;
  Duration totalVideoDuration = Duration(seconds: 0);

  @override
  void initState() {
    super.initState();
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: <Widget>[
          CameraPreview(
            widget.controller
          ),
          Positioned(
            bottom: 5.0,
            left: 5.0,
            child: RaisedButton(
              child: Text('Stop'),
              onPressed: () {
                if( widget.controller.value.isRecordingVideo || widget.controller.value.isRecordingPaused ) {
                  print('Stop recording');
                  widget.controller.stopVideoRecording().then(
                    (_) {
                      print('###########################');
                      print('Video recording stopped');
                      totalVideoDuration = Duration(seconds: 0);
                      print(path);
                      filePath = File(path);
                      print(filePath);
                      print('###########################');
                    }
                  );
                } else {  
                  print('No active video recording to stop');
                }
              },
            ),
          ),
          Positioned(
            bottom: 5.0,
            right: 5.0,
            child: GestureDetector(
              child: Container(
                color: Colors.white,
                child: SizedBox(
                  child: Center(
                    child: Text(
                      'Record',
                      style: TextStyle(
                        fontSize: 16.0,
                        color: Colors.red
                      ),
                    )
                  ),
                  height: 40.0,
                  width: 60.0,
                ),
              ),
              onLongPressStart: (data ) {
                print('#######################################################');
                print('onLongPressStart');

                if( ! widget.controller.value.isRecordingVideo ) {
                  print('When user long presses and holds for the first time');
                  dateTimeStart = DateTime.now();
                  print('Video start time: $dateTimeStart');
                  getTemporaryDirectory().then(
                    (dir) {
                      path = dir.path + '$dateTimeStart.mp4';
                      print('Starting video recording');
                      widget.controller.startVideoRecording(path).then(
                        (_) {
                          print('**************');
                          print('Video recording started');
                          print('Video file name: $path');
                          print('**************');
                        }
                      );
                    }
                  );
                }
                
                print('Before resuming the video');
                print('Total video duration: ${totalVideoDuration.inSeconds} s');
                if( ( widget.controller.value.isRecordingVideo || widget.controller.value.isRecordingPaused ) ) {
                  if( totalVideoDuration.inSeconds <= intervalTime ) {
                    print('Resuming');
                    widget.controller.resumeVideoRecording().then(
                      (_) {
                        print('**************');
                        print('Video recording resumed');
                        dateTimeStart = DateTime.now();
                        print('Current time: $dateTimeStart');
                        print('**************');
                      }
                    );
                  } else {
                    print('Total video duration is greater than 30s');
                    print('Total video duration: ${totalVideoDuration.inSeconds} s');
                    print('Stopping');
                    print('Debug>>');
                    print(widget.controller.value.isRecordingVideo);
                    print(widget.controller.value.isRecordingPaused);
                    widget.controller.stopVideoRecording().then(
                      (_) {
                        print('**************');
                        print('Video recording is stopped');
                        totalVideoDuration = Duration(seconds: 0);
                        print(path);
                        filePath = File(path);
                        print(filePath);
                        print('**************');
                      }
                    ).catchError( (err) {
                      print('**************');
                      print('Error while stopping the video');
                      totalVideoDuration = Duration(seconds: 0);
                      print(err.toString());
                      print('**************');
                    });
                  }
                } 
                print('#######################################################');
              },
              onLongPressEnd: (data) {
                print('#######################################################');
                print('onLongPressEnd');
                if( widget.controller.value.isRecordingVideo || widget.controller.value.isRecordingPaused ) {
                  print('Pausing');
                  widget.controller.pauseVideoRecording().then(
                    (_) {
                      print('**************');
                      print('Video recording is paused');
                      DateTime currentTime = DateTime.now();
                      print('Current time: $currentTime');
                      int tempTotalDuration = totalVideoDuration.inSeconds;
                      print('Previous total duration: $tempTotalDuration');
                      totalVideoDuration = currentTime.difference(dateTimeStart);
                      print('Intermediate total duration: ${totalVideoDuration.inSeconds} s');
                      totalVideoDuration = Duration(seconds: totalVideoDuration.inSeconds + tempTotalDuration );
                      print('Total Video duration : ${totalVideoDuration.inSeconds} s');
                      print('**************');
                    }
                  );
                }
                print('#######################################################');
              },
            ),
          ),
          Positioned(
            left: 5.0,
            top: 25.0,
            child: RaisedButton(
              child: Text('View'),
              onPressed: () {
                if( filePath != null ) {
                  //Navigator.push(
                  //  context, 
                  //  MaterialPageRoute(
                  //    builder: (context) => VideoPlayerApp(filePath)
                  //  )
                  //); 
                }
              },
            ),
          )
        ],
      ),
    );
  }
}
4 Likes

Thank you for your detailed response.

1 Like

Thank you this is amazing! Appreciate all your effort!

4 Likes