0
votes

Hi was just wondering if anyone knows a way that i can run a batch file that contains multiple "start ffmpeg" commands, that allows me to kill it using a batch file at some random point in time.

I have one batch that starts 4 videos recording from a rtsp feed to file. And another one that taskkills that ffmpeg process. The problem is that i can run these successfully by running in cmd prompt, but when i try to use exec(record.bat) or popen() etc, it runs the ffmpeg process in the background, and the stoprecord.bat can't kill it error is:

The Process with PID x <child process of PID y> could not be terminated.


Reason: This Process can only be termintated forcefully (with /f option)

I don't want to force it, because the mp4 file corrupts when you force close it. When i run the bat files directly i dont need that force option. I have tried giving the folders full permissions for the IIS_IUSRS user, i have made the bat and folder creater as IIS_IUSRS (thought the mkdir in the batch gives not permission to IIS usr which it is recording the video to).

Any one have any clue why this wouldnt work. I have put the bat files below and the php script which calls them.

Record.bat

cd C:\inetpub\wwwroot\ESTF\batch
tasklist /FI "IMAGENAME eq ffmpeg_sr.exe" | find ":" > NUL
if errorlevel 1 exit
set MEDIA_DIR=C:\inetpub\wwwroot\ESTF\media\recordings
set WEB_DIR=C:\inetpub\wwwroot\estf\
set VLC_DIR=C:\Program Files\VideoLAN\VLC
set ROOM=simroom
set M=1
set N=1
set CURRENT_DAY=day1
set FFMPEG_DIR=C:\inetpub\wwwroot\ESTF\ffmpeg\bin                
call "date.bat"
if not exist %MEDIA_DIR%\curDate.txt (
    mkdir %MEDIA_DIR%
    icacls %MEDIA_DIR% /grant Everyone:(f)
    echo %DATESTR%>%MEDIA_DIR%\curDate.txt
    echo %CURRENT_DAY%>%MEDIA_DIR%\curDay.txt
    goto :LOOP2
)
if exist %MEDIA_DIR%\curDate.txt (
    set /p STORED_DATE=<C:\inetpub\wwwroot\ESTF\media\recordings\curDate.txt
)

if /I %STORED_DATE%==%DATESTR% (
        set /p CURRENT_DAY=<C:\inetpub\wwwroot\ESTF\media\recordings\curDay.txt
        goto :LOOP2
)
if /I NOT %STORED_DATE%==%DATESTR% (
    echo %DATESTR%>%MEDIA_DIR%\curDate.txt
    goto :LOOP1
)

:LOOP1
    set DAY_LOOP=%MEDIA_DIR%\day%M%
    if exist %DAY_LOOP% (
        set /a M = %M%+1
        goto :LOOP1
    )
    if not exist %DAY_LOOP% (
        mkdir %DAY_LOOP%
        icacls %DAY_LOOP% /grant Everyone:(f)
    )
    set CURRENT_DAY=day%M%
    @echo %CURRENT_DAY%>%MEDIA_DIR%\curDay.txt

:LOOP2
    set CURRENT_ROOM=%MEDIA_DIR%\%CURRENT_DAY%\%ROOM%\Team%N%
    if exist %CURRENT_ROOM% (
        set /a N = %N%+1
        goto :LOOP2
    )
    if not exist %CURRENT_ROOM% (
        mkdir %CURRENT_ROOM%
        icacls %CURRENT_ROOM% /grant Everyone:(f)
    )

cd %FFMPEG_DIR%

echo %CURRENT_ROOM%>%MEDIA_DIR%\%CURRENT_DAY%\%ROOM%\teamNo.txt
echo recording>%WEB_DIR%\srRecording.txt
start ffmpeg_sr  -i rtsp://192.168.0.50:554/Streaming/Channels/1 -c:v copy -c:a libmp3lame -strict experimental "%CURRENT_ROOM%\1.mp4"
start ffmpeg_sr  -i rtsp://192.168.0.51:554/Streaming/Channels/1 -c:v copy "%CURRENT_ROOM%\2.mp4"
start ffmpeg_sr  -i rtsp://192.168.0.52:554/Streaming/Channels/1 -c:v copy "%CURRENT_ROOM%\3.mp4"
start ffmpeg_sr  -i rtsp://192.168.0.21:554/Streaming/Channels/1 -c:v copy "%CURRENT_ROOM%\4.mp4"
start ffmpeg_sr -f dshow -i audio="Microphone (High Definition Audio Device)" -c:a libmp3lame -strict experimental "%CURRENT_ROOM%\0.mp3"
exit

Stoprecord.bat

taskkill /im ffmpeg_sr.exe /t
set WEB_DIR=c:\inetpub\wwwroot\estf\
set FFMPEG_DIR=C:\inetpub\wwwroot\ESTF\ffmpeg\bin\
echo stopped>%WEB_DIR%\srRecording.txt
set /p CURRENT_DAY=<C:\inetpub\wwwroot\ESTF\media\recordings\curDay.txt
set /p CURRENT_ROOM=<C:\inetpub\wwwroot\ESTF\media\recordings\%CURRENT_DAY%\simroom\teamNo.txt
echo %CURRENT_ROOM%
cd %FFMPEG_DIR%
ffmpeg -i %CURRENT_ROOM%/ -i %CURRENT_ROOM%/0.mp3 -c:v copy -c:a copy -strict experimental -map 0:v:0 -map 1:a:0 %CURRENT_ROOM%/1.mp4
ffmpeg -i %CURRENT_ROOM%/1_temp.mp4 -c:v copy -c:a copy -strict experimental -map 0:v:0 -map 1:a:0 %CURRENT_ROOM%/1.mp4
REM del %CURRENT_ROOM%\1_temp.mp4
del %CURRENT_ROOM%\0.mp3
exit

record.php

<?php
echo exec('whoami');
//$recordPath = 'c:\inetpub\wwwroot\estf\batch\srRecord.bat';
//exec('c:\inetpub\wwwroot\estf\batch\srRecord.bat');
$handle = popen('start c:\inetpub\wwwroot\estf\batch\srRecord.bat exit','r');
pclose($handle);
echo $handle;
?>

stoprecord.php

<?php
//exec('c:\inetpub\wwwroot\estf\batch\srRecordStop.exe /dev/null');
$handle = popen('start c:\inetpub\wwwroot\estf\batch\srRecordStop.bat','r');
pclose($handle);
//die();
echo $handle;
?>

I have tried exec(), pclose(popen()), shell_exec(), tried adding /dev/nul & to both the php file and ffmpeg in the batch file.

Regards,

Mitchell

1
It looks like this problem has been well described in an ffmpeg ticket. It seems that ffmpeg has implemented sending 'q' to the app to gracefully stop a stream recording, but I have no idea how to do this for a background process. Maybe you could try a couple other binaries to kill your streams gracefully: @kill or nircmd closeprocess?UltrasoundJelly
Ok well is there another method where i can run the script on the computer for an unset period of time, then kill it on command? Telnet, ssh?Mitchell Day

1 Answers

0
votes

So I ended up using a couple of things. Firstly i converted the batch to an exe. I then created a task in task scheduler. I then used pclose(popen($com,'r')); to run the task which started the exe file and opened the ffmpeg processes on the desktop.

Obviously not a direct route to executing the ffmpeg, but it works for my system. This allows me to make another event that cancels them(or just run a exec(taskkill ffmpeg.exe) command.