Genymobile / scrcpy

Display and control your Android device
Apache License 2.0
108.59k stars 10.45k forks source link

recorded video is corrupted #5122

Open vinayhatyal opened 1 month ago

vinayhatyal commented 1 month ago

Checked FAQ Checked open Issues

Environment

OS: Windows 11 Scrcpy version: 2.5 Installation method: Windows release/ through choco Device model: infix and mia2 Android version: Android 11

Describe the bug

I'm using this scrcpy to record the device screen in mp4 format, but without the floating window(--no-window), and terminating the scrcpy.exe by their PID(taskkill /PID ). if i do this, the recorded video is corrupted. instead if i close by clicking the close button or by killing the process by removing the --no-window flag then i can play the video. This issue happens only in MS Windows and works fine in Linux.

But i want to record the video without the the window showing and if possible please provide gracefully closing option from cli

here is a code snippet how i used:

issue causing snippet=> exec(scrcpy --record=video.mp4 --max-fps 15 --max-size 480 --no-window, (error, _stdout) => { console.log("recording....") }

working snippet =>
issue causing snippet=> exec(scrcpy --record=video.mp4 --max-fps 15 --max-size 480, (error, _stdout) => { console.log("recording....") }

and here is the code how i find PIDs and killing them =>

    function stopScrcpy() {
        const findPIDs = spawn('tasklist', ['/FI', 'IMAGENAME eq scrcpy.exe']);
        let output = '';
        let errorOutput = '';
        findPIDs.stdout.on('data', (data) => {
            output += data.toString();
        });
        findPIDs.stderr.on('data', (data) => {
            errorOutput += data.toString();
        });
        findPIDs.on('close', (code) => {
            if (code !== 0) {
                console.error(`Error finding PIDs: ${errorOutput}`);
                return;
            }
            const pids = output.match(/(\d+)\s+Console\s+\d+\s+[\d,]+ K/g)
                .map(match => match.split(/\s+/)[0]);
            if (pids.length === 0) {
                console.log('No scrcpy.exe processes found');
                return;
            }
            pids.forEach(pid => {
                const killProcess = spawn('taskkill', ['/PID', pid]);
                killProcess.stdout.on('data', (data) => {
                    console.log(`stdout for PID ${pid}: ${data}`);
                });
                killProcess.stderr.on('data', (data) => {
                    console.error(`stderr for PID ${pid}: ${data}`);
                });
                killProcess.on('close', (code) => {
                    if (code === 0) {
                        console.log(`PID ${pid} terminated successfully`);
                    } else {
                        console.log(`taskkill process for PID ${pid} exited with code ${code}`);
                    }
                });
                killProcess.on('error', (error) => {
                    console.error(`Error stopping PID ${pid}: ${error.message}`);
                });
            });
        });
        findPIDs.on('error', (error) => {
            console.error(`Error finding PIDs: ${error.message}`);
        });
  }
rom1v commented 1 month ago

i find PIDs and killing them

If you kill the process abruptly, the muxer will never have a chance to write the footer, so your mp4 will be corrupted. Although it would still be incorrect for Matroska files (mkv), the resulting files should still be playable).

You must send Ctrl+C on Windows instead to interrupt (and never close the cmd console by clicking the X, it would kill abruptly).

tingfengwanxiao commented 1 month ago

Can we save the currently recorded video when an exception occurs, such as exiting? That should solve the problem

vinayhatyal commented 1 month ago

Can we save the currently recorded video when an exception occurs, such as exiting? That should solve the problem

The problem lies in saving the video correctly. Currently, I can obtain a playable video only by manually closing the scrcpy application using the X button. However, if I hide the scrcpy window using the --no-window option, I have to terminate the scrcpy processes either by their PID or by using Ctrl+C, both of which result in a corrupted video.

rom1v commented 1 month ago

I hide the scrcpy window using the --no-window option, I have to terminate the scrcpy processes either by their PID or by using Ctrl+C, both of which result in a corrupted video.

Using Ctrl+C from the terminal should work correctly, without corrupting video.

If it does not (I cannot test currently), this is a bug. If so, please test v2.4 (before --no-window was added) to confirm.

vinayhatyal commented 1 month ago

I hide the scrcpy window using the --no-window option, I have to terminate the scrcpy processes either by their PID or by using Ctrl+C, both of which result in a corrupted video.

Using Ctrl+C from the terminal should work correctly, without corrupting video.

If it does not (I cannot test currently), this is a bug. If so, please test v2.4 (before --no-window was added) to confirm.

it seems there is issue with <cntrl+c> itself, here are the reference videos that could help analyze.

tested with version 2.5 : v2.5.webm tested with version 2.4: v2.4.webm

You can observe there is no info saying recording complete if i terminate by clicking <cntr+c> in the console, but it showed if i close by clicking close button.

rom1v commented 1 month ago

Could you please test with scrcpy v2.0, which uses an older SDL version?

vinayhatyal commented 1 month ago

Could you please test with scrcpy v2.0, which uses an older SDL version?

i tried with version 2.0. but the results are same.

here are the logs, you can see first time i terminated with <cntrl+c> and second one i terminated with close button.

C:\Users\sanji\poc\Videos>scrcpy --record=video1_v2.mp4 scrcpy 2.0 <https://github.com/Genymobile/scrcpy>

C:\Users\sanji\poc\Videos>scrcpy --record=video2_v2.mp4 scrcpy 2.0 <https://github.com/Genymobile/scrcpy> C:\ProgramData\chocolatey\lib\scrcpy\tools\scrcpy-win64-v2... file pushed, 0 skipped. 99.5 MB/s (52867 bytes in 0.001s) [server] INFO: Device: INFINIX MOBILITY LIMITED Infinix X682B (Android 10) [server] WARN: Audio disabled: it is not supported before Android 11 INFO: Recording started to mp4 file: video2_v2.mp4 INFO: Renderer: direct3d WARN: Demuxer 'audio': stream explicitly disabled by the device WARN: Audio stream recording disabled INFO: Initial texture: 720x1640 INFO: Recording complete to mp4 file: video2_v2.mp4 WARN: Killing the server...

you can observer, if i do <cntrl+c> i'm not getting these "INFO: Recording complete to mp4 file: video2_v2.mp4 WARN: Killing the server..." s o it leads to corrupted videos.

rom1v commented 1 month ago

OK, I can't explain why Ctrl+c does not work as expected on your machine. Scrcpy explicitly catches Ctrl+c on Windows:

https://github.com/Genymobile/scrcpy/blob/bbfac9ae1fba08a045557abe9612703ace8a3890/app/src/scrcpy.c#L149

Maybe a cmd.exe configuration or something?

vinayhatyal commented 1 month ago

OK, I can't explain why Ctrl+c does not work as expected on your machine. Scrcpy explicitly catches Ctrl+c on Windows:

https://github.com/Genymobile/scrcpy/blob/bbfac9ae1fba08a045557abe9612703ace8a3890/app/src/scrcpy.c#L149

Maybe a cmd.exe configuration or something?

Thank you @rom1v for your help and quick responses to my comments. I appreciate your time and support. I'll try to figure out the issue.

Aefun-ayi commented 1 month ago

好吧,我无法解释为什么 Ctrl+c 在你的机器上不能按预期工作。Scrcpy 在 Windows 上明确捕获了 Ctrl+c: https://github.com/Genymobile/scrcpy/blob/bbfac9ae1fba08a045557abe9612703ace8a3890/app/src/scrcpy.c#L149

也许是 cmd.exe 配置或者别的什么?

谢谢 @rom1v 感谢您的帮助和对我评论的快速回复。感谢您的时间和支持。我会尽力解决问题。

Hello, have you solved your problem? I have this problem now

rom1v commented 1 month ago

Interesting. I don't know why. I re-tested, for me it works as expected, I have Recording complete to mp4 file: file.mp4 at the end when I Ctrl+c.

rom1v commented 1 month ago

It you run

scrcpy -Vverbose --no-window --record=file.mp4

then Ctrl+c, what's the full output?

vinayhatyal commented 1 month ago

It you run

scrcpy -Vverbose --no-window --record=file.mp4

then Ctrl+c, what's the full output?

C:\Users\I5343\Pictures>scrcpy -Vverbose --no-window --record=file.mp4 scrcpy 2.5 <https://github.com/Genymobile/scrcpy>

i have attached reference video also, with and without --no-window command vid2.webm vid1.webm

rom1v commented 1 month ago

Thank you. I guess this is the same with the Windows release (instead of the chocolatey package)?

Something probably intercepts Ctrl+c at the system level and kills the process. Any antivirus/firewall/something enabled?

rom1v commented 1 month ago

Is it powershell or cmd?

vinayhatyal commented 1 month ago

好吧,我无法解释为什么 Ctrl+c 在你的机器上不能按预期工作。Scrcpy 在 Windows 上明确捕获了 Ctrl+c: https://github.com/Genymobile/scrcpy/blob/bbfac9ae1fba08a045557abe9612703ace8a3890/app/src/scrcpy.c#L149

也许是 cmd.exe 配置或者别的什么?

谢谢 @rom1v 感谢您的帮助和对我评论的快速回复。感谢您的时间和支持。我会尽力解决问题。

Hello, have you solved your problem? I have this problem now

hello, i have a temporary solution for this, i tried killing process gracefully, it worked. I'm dropping the code below, this might be helpful.

code: "@echo off setlocal set SCRCPY_BINARY=scrcpy.exe set OUTPUT_FILE=output.mp4 set PID_FILE=%TEMP%\scrcpyrecord%RANDOM%.pid set LOG_FILE=%TEMP%\scrcpyrecord%RANDOM%.log :CHECK_EXISTING_PROCESSES rem Kill any existing scrcpy processes before starting for /f "skip=1 tokens=2" %%a in ('tasklist /fi "imagename eq scrcpy.exe" /fo csv /nh') do ( echo %%a > %PID_FILE% set PID=%%a echo Killing process with PID: %%a taskkill /PID %%a /F >nul 2>&1 timeout /T 2 /NOBREAK >nul ) :START if "%1"=="start" ( echo Starting recording... start "" /B "%SCRCPY_BINARY%" --no-control --max-size 480 --record %OUTPUT_FILE% > %LOG_FILE% 2>&1 timeout /T 2 /NOBREAK >nul for /f "skip=1 tokens=2" %%a in ('tasklist /fi "imagename eq scrcpy.exe" /fo csv /nh') do ( echo %%a > %PID_FILE% set PID=%%a ) if defined PID ( echo Recording started. PID: %PID% ) else ( echo Failed to start recording or capture PID. ) exit /b 0 ) :STOP if exist %PID_FILE% ( @echo off setlocal enabledelayedexpansion :: Initialize a counter set count=0 :: Loop through the tasklist output for /f "tokens=2 delims=," %%i in ('tasklist /FI "IMAGENAME eq scrcpy.exe" /FO CSV /NH') do ( set /a count+=1 if !count! equ 2 ( :: Print the PID of the second process echo Terminating process with PID: %%i :: Kill the process taskkill /PID %%i :: Exit the script exit /b ) ) :: Inform if no second process was found echo No second scrcpy.exe process found. if exist %OUTPUT_FILE% ( echo Recording stopped. Check %OUTPUT_FILE% for the recording. ) else ( echo No output file found. Check %LOG_FILE% for errors. ) ) else ( echo No recording process found. ) endlocal exit /b 0"

1: save the file with .bat extension. 2: in cmd, cd C:\path\to\your\script.bat
3:if required, do this chmod +x script.bat
4: script.bat start/stop

reference video: scriptvideo.webm

*Note: if you use "--no-window", recorded video will be corrupted.

vinayhatyal commented 1 month ago

Is it powershell or cmd?

cmd

vinayhatyal commented 1 month ago

Thank you. I guess this is the same with the Windows release (instead of the chocolatey package)?

Something probably intercepts Ctrl+c at the system level and kills the process. Any antivirus/firewall/something enabled?

yes, in both the ways i tried installing scrcpy, same results.

rom1v commented 1 month ago

cmd

What's your terminal?

When I run cmd.exe, it does not look like this at all.

Try with open_a_terminal_here.bat or Win+r, cmd.exe.

vinayhatyal commented 1 month ago

cmd

What's your terminal?

When I run cmd.exe, it does not look like this at all.

strange!, i use normal command prompt only (cmd)

rom1v commented 1 month ago

It looks like this:

cmd

vinayhatyal commented 1 month ago

cmd

What's your terminal? When I run cmd.exe, it does not look like this at all.

strange!, i use normal command prompt only (cmd)

i tried this also 1: Win+r : cmd.exe. but there was no betterment.

vinayhatyal commented 1 month ago

It looks like this:

cmd

its only a UI difference(might be difference in OS version or laptop vendor),but in windows there will be only one command prompt and it work same for everyone right.

rom1v commented 1 month ago

Non only, this terminal is also "limited" (it cannot be resized for example), but above all it probably correctly sends Ctrl+c to the running process.

vinayhatyal commented 1 month ago

Non only, this terminal is also "limited" (it cannot be resized for example), but above all it probably correctly sends Ctrl+c to the running process.

vid.webm

rom1v commented 1 month ago

OK, I don't know Windows very well, but IMO the behavior of Ctrl+c is definitely handled differently in your "terminal" app (whichever it is).

EDIT: I guess your app is Windows Terminal: https://apps.microsoft.com/detail/9n0dx20hk701

vinayhatyal commented 1 month ago

OK, I don't know Windows very well, but IMO the behavior of Ctrl+c is definitely handled differently in your "terminal" app (whichever it is).

EDIT: I guess your app is Windows Terminal: https://apps.microsoft.com/detail/9n0dx20hk701

yes, but you can see in the above video, i tried opening a new cmd tab from windows terminal and ran the given command. And, in any way cntrl+c generates an interrupt signal (SIGINT) which is sent to the foreground process. This signal is intended to terminate the process.

rom1v commented 1 month ago

If you manage to start the "old" cmd terminal (not just cmd.exe run in Windows Terminal) in some way and confirm that Ctrl+c works, it might be interesting to report the issue to https://github.com/microsoft/terminal

vinayhatyal commented 1 month ago

As Windows 11 is now widely used, it would be helpful if you could provide a way to start and stop 'scrcpy.exe' directly from the command line interface (CLI) without requiring additional steps. This would ease the process for users. Thanks again for your time and assistance @rom1v.