Vlad Stefan
Vlad Stefan

Reputation: 9

ffmpeg crash when updating overlay file (c# console app)

I am trying to develop a console app that can record the screen and have cpu/ram/gpu usage of the machine noted on the recording. The problem i am facing is that after a while (2-3 hours) the recording stops because ffmpeg is trying to read the file text while my C# code tries to update the file. I managed to find out that I should use a temp file and replace the original instead of rewriting the whole file but that way I encounter another problem, ffmpeg will try to read the file while the file is replaced or even for that split second when is considered deleted. Any ideas what I should do? How should the method with the temp file be managed or how can I make the method that updates the same file stable? I was even thinking to increment the ffmpeg reload frames since it might narrow the chances of crashing but it's not a 100% crash proof solution.

Error message received from ffmpeg with updating only the text from the file:

Error: [Parsed_drawtext_0 @ 000001e68fd95dc0] [FILE @ 0000009fb7ffee70] Error occurred in CreateFileMapping()
Error: [Parsed_drawtext_0 @ 000001e68fd95dc0] The text file 'OverlayFiles/OverlayFile_MyPC.txt' could not be read or is empty
Error: [vf#0:0 @ 000001e68fd48300] Error while filtering: Operation not permitted
Error: [vf#0:0 @ 000001e68fd48300] Task finished with error code: -1 (Operation not permitted)

Error message received from ffmpeg with the use of a temp file that's replacing the original file:

Error: [Parsed_drawtext_0 @ 0000014c815e6200] [FILE @ 000000253d7fee70] Cannot read file 'OverlayFiles/OverlayFile_MyPC.txt': Permission denied
Error: [Parsed_drawtext_0 @ 0000014c815e6200] The text file 'OverlayFiles/OverlayFile_MyPC.txt' could not be read or is empty
Error: [vf#0:0 @ 0000014c81597280] Error while filtering: Permission denied
Error: [vf#0:0 @ 0000014c81597280] Task finished with error code: -13 (Permission denied)
Error: [vf#0:0 @ 0000014c81597280] Terminating thread with return code -13 (Permission denied)

ffmpeg arguments:

string arguments = $"-video_size 1920x1080 -framerate 30 -f gdigrab -i desktop -c:v libx264rgb -crf 0 -preset ultrafast -color_range 2 " +
                   $"-vf \"drawtext=fontfile=C\\\\:/Windows/fonts/consola.ttf:fontsize=30:fontcolor='white':textfile={overlayFilePath_}:boxcolor=0x00000080:box=1:x=10:y=H-210:reload=1\" \"" + 
                   outputFile + "\"";

The code that updates the overlay file (1st version):

public void UpdateOverlayText(string filePath)
{
    string usage = GetSystemUsage(filePath);  // Get the system usage data

    try
    {
        // Open the file with FileShare.ReadWrite to allow other processes to read it while writing
        using (var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
        {
            using (var writer = new StreamWriter(fileStream))
            {
                writer.Write(usage);  // Write the system usage data to the file
            }
        }

        // Ensure file permissions are set correctly after writing
        SetFilePermissions(filePath);
    }
    catch (IOException ex)
    {
        Console.WriteLine($"Error updating overlay file: {ex.Message}");
    }
}

(UPDATE)Code that updates overlay file using MemoryStream:

public void UpdateOverlayText(string filePath)
{
    string usage = GetSystemUsage(filePath);

    try
    {
        using (var memoryStream = new MemoryStream())
        {
            using (var writer = new StreamWriter(memoryStream))
            {
                writer.Write(usage);
                writer.Flush();

                memoryStream.Position = 0;

                File.WriteAllBytes(filePath, memoryStream.ToArray());
            }
        }

        SetFilePermissions(filePath);
    }
    catch (IOException ex)
    {
        Console.WriteLine($"Error updating overlay file: {ex.Message}");
    }
}

Code tested using MemoryStream and Temp file:

public void UpdateOverlayText(string filePath)
{
    string usage = GetSystemUsage(filePath);
    string tempFilePath = filePath + ".tmp";
    try
    {
        // Write to a temporary file first
        using (var memoryStream = new MemoryStream())
        {
            using (var writer = new StreamWriter(memoryStream))
            {
                writer.Write(usage);
                writer.Flush();

                memoryStream.Position = 0;
                File.WriteAllBytes(tempFilePath, memoryStream.ToArray());
            }
        }
        File.Replace(tempFilePath, filePath, null);
    }
    catch (IOException ex)
    {
        Console.WriteLine($"Error updating overlay file: {ex.Message}");
    }
    finally
    {
        if (File.Exists(tempFilePath))
        {
            File.Delete(tempFilePath);
        }
    }
}

Thanks in advance for your help and sorry for any typo or wrong phrases I used.

Upvotes: 0

Views: 35

Answers (0)

Related Questions