4

i try to running testcase using selenium python and want to record video on every testacases, but when i try the output is always corrupted. FFMPEG process are running, no error appear on the output line. I attach my code, Please anyone help me is there anything i need to add or remove

here's the first file, for recorder :

import subprocess
from subprocess import Popen
from subprocess import call


class recorderMethod():
    videoRecording = None

    @staticmethod
    def recorder_start(res,name):
        rec_lib          = 'ffmpeg -y -rtbufsize 2000M -f dshow  -i video="screen-capture-recorder" -s '
        resolution       = res
        buffer           = ' -b:v 512k -r 20 -vcodec libx264 '
        filename         = name
        extension        = '.mp4'
        complete_command = rec_lib+resolution+buffer+filename+extension

        recorderMethod.videoRecording = Popen(str(complete_command))

    @staticmethod
    def recorder_stop():
        if recorderMethod.videoRecording.poll() is None:
            call('taskkill /F /T /PID ' + str(recorderMethod.videoRecording.pid))

here's the main test file for record the video

import unittest
import recorder_main
from selenium import webdriver
from time import sleep

class recordingTest(unittest.TestCase):
    #init test
    browser         = webdriver.Chrome()
    baseurl         = 'http://www.facebook.com/'
    record          = recorder_main.recorderMethod
    
    #setup
    def setUp(self):
        #declare to use browser
        self.driver = recordingTest.browser
        #make variable for easy access
        driver = self.driver
        #maximize Firefox
        driver.maximize_window()
        #go to maukerja
        driver.get(recordingTest.baseurl)

    #test001
    def test_001_record(self):
        #start recording
        recordingTest.record.recorder_start('1920x1080','Test_Sleep')
        sleep(10)
        #stop_recording
        recordingTest.record.recorder_stop()


    #teardown
    def test_999_ShutDownTest(self):
        self.driver.close()
        
if __name__ == '__main__':
    unittest.main(exit=False)

2 Answers2

2

You need to gracefully stop FFmpeg:

You may use the following code:

import signal

# ...

# https://stackoverflow.com/questions/9722624/how-to-stop-ffmpeg-remotely  
# https://stackoverflow.com/questions/27356837/send-sigint-in-python-to-os-system
def recorder_stop():
    if recorderMethod.videoRecording.poll() is None:
        recorderMethod.videoRecording.send_signal(signal.CTRL_C_EVENT)
        sleep(3)  # To be sure that the process ends  

The code you are using for closing FFmpeg is:

call('taskkill /F /T /PID ' + str(recorderMethod.videoRecording.pid))

Closing FFmpeg using taskkill, results a corrupted file.
FFmpeg is terminated without finish writing the video stream to the output file.

In old versions of FFmpeg recording is stopped by pressing Q (I don't know how old).
For new versions, the recording is stopped by pressing Ctrl-C.
Lets assume we are using a new version.

Sending signal.CTRL_C_EVENT is equivalent to quitting by pressing Ctrl-C.


Note:
In case you want FFmpeg to record the screen for 10 seconds and terminate, you may add -t 10 (output) argument, without executing recorder_stop().

Rotem
  • 30,366
  • 4
  • 32
  • 65
  • You are correct, i'm not gracefully stop FFMPEG when it's encoding the file, also i change configuration when start recording, i'll post on the new answer – Didit Setiawan Apr 28 '21 at 03:51
1

First i change this line

rec_lib          = 'ffmpeg -y -rtbufsize 2000M -f dshow  -i video="screen-capture-recorder" -s '

into this line

rec_lib          = 'ffmpeg -y -rtbufsize 2000M -f dshow -i video="screen-capture-recorder" -b:v 512k -r 20 -vcodec libx264 -strict -2 -preset slow -pix_fmt yuv420p -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" -f mp4 '

and then for stopping i adding this :

recorderMethod.videoRecording.stdin.write('q'.encode("GBK"))
recorderMethod.videoRecording.communicate() 
if recorderMethod.videoRecording.poll() is None:
   call('taskkill /F /T /PID ' + str(recorderMethod.videoRecording.pid))