14

The Situation: I'm using ffmpeg (via .net) to save video files. I can get the output from ffmpeg but I dont know how can I customize the output to have better result.

My Problem: My problem is, there is no certain difference between successful and failed operation.

last line of success:

video:1006kB audio:134kB subtitle:0 global headers:0kB muxing overhead 0.943510%

last lines from fails

c:\x\test-9-8/30/2012-9:29:56-AM.mp4: Invalid argument

rtmp://cdn.tv/cdn-live39/definst/stream01: Unknown error occurred

My Question: Is there an option (or command line parameter) to add some sort of return code (200: success, 500: error, etc)

Thanks!

PS: I saw this topic How to tell if ffmpeg errored? but there is no number before/after last line. I think the last version doesnt have number anymore.

Community
  • 1
  • 1
dvdmn
  • 6,456
  • 7
  • 44
  • 52
  • 1
    I've an idea (not ideal solution).. I can check the target file for exist or not when all the process is done. if the file is exist and bigger than zero byte I would assume the process was successful. If the target file not exist get last line of the output and show it as error message.. – dvdmn Aug 30 '12 at 16:20
  • not a good solution. Did that, because I thought naïvely "ffmpeg won't create, or at least keep, the output file if there is an error", but it does. Check exist status = 0 means everything is fine. – Lideln Kyoku May 27 '23 at 11:36

3 Answers3

7

I know this is very old but as i came across and found no other reliable answer and after some more testing:

The suggestion with checking for return of 0 is in general a good advice - but does not help in all cases. The other idea with checking if the file exists is also good - but again - does not help in all cases.

For example when the input file is a mp3 file that has an embedded cover - then ffmpeg does (in my tests) use this image and extracts that one as an (unusable) video file.

What i do now is to have debug level output and parse it for the number of muxed packets.

ffmpeg -i "wildlife.mp4" -c:v copy -an -sn "out.mp4" -y -loglevel debug 2> wildlife.txt

With a regex i search for this text:
Output stream .+ (video): [0-9][0-9]+ packets muxed \([0-9][0-9]+ bytes\)

(this assumes that every video has more than 9 packets - could of course be optimized for really short videos).

Of course for RTMP or other settings the output may differ but i think to parse the full output stream is the only option.

Eleasar
  • 529
  • 9
  • 20
  • is there an extensive list of cases in which the return or the file fail to check for errors? – cregox May 10 '21 at 12:11
5

You could just check the exit code returned by ffmpeg. It should return 0 on success, anything else means it failed.

sashoalm
  • 75,001
  • 122
  • 434
  • 781
  • 2
    Is this guaranteed to be reliable? – nafg May 02 '16 at 09:04
  • 11
    This does not work. FFmpeg does not (always) return non 0 on errors – DIDoS Oct 25 '16 at 21:11
  • 6
    @DIDoS Can you give an example? – sashoalm Oct 26 '16 at 06:34
  • 1
    how do i check that why it failed? I have added the ffmpeg as library simple tried to follow this link http://stackoverflow.com/questions/23683960/android-video-encoding-with-fr-and-resolution-manipulation/23815402#23815402 – Arpan Sharma Apr 27 '17 at 06:15
  • 1
    @ArpanSharma That question is for using ffmpeg as executable, not as library. But you can [ask a separate question](https://stackoverflow.com/questions/ask) for libraries. – sashoalm Apr 27 '17 at 07:05
  • 1
    @sashoalm I just have to compress a video before uploading in my android app. whatever way that seems fit.Can you guide me please – Arpan Sharma Apr 27 '17 at 07:08
  • 1
    @ArpanSharma [Ask a new question](https://stackoverflow.com/questions/ask). – sashoalm Apr 27 '17 at 07:10
  • 1
    is there an extensive list of cases in which this return fail to check for errors? – cregox May 10 '21 at 12:12
1

You can run ffmpeg in -v error mode and have it return errors into a text file, see here: https://superuser.com/questions/100288/how-can-i-check-the-integrity-of-a-video-file-avi-mpeg-mp4 You can combine this with encoding without the null output but you will only be able to read the results from the text file.

Or you can have an additional script that will follow-up on the errors. Here is a Python example, which checks for file integrity, notice the if stdout clause. This will basically re-check encoded file if you need to see normal output first.

Solution 1:

import subprocess
import os
import sys
import re

def check_video(files):
    if type(files) == str:
        files = [files]

    for file in files:
        print(f"Checking {file}...")
        command_line = f'ffmpeg -v error -i "{file}" -map 0:v -map 0:a? -vcodec copy -acodec copy -f null -'
        base_name = os.path.splitext(file)[0]
        extension = os.path.splitext(file)[1]

        process = subprocess.Popen(command_line, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        stdout, stderr = process.communicate()
        return_code = process.returncode
        pid = process.pid

        print(f"Base: {base_name}")
        print(f"Extension: {extension}")
        print(f"RC: {return_code}")

        if stdout:
            allowed_errs = ["invalid as first byte of an EBML number"]
            stdout_detect = stdout.decode().split("\n")

            for error in allowed_errs:
                if error not in stdout_detect[0] or len(stdout_detect) > 2:
                    print(f"Errors!")
                    print(os.path.splitext(file)[1])
                    os.rename(file, f"{file}.error")
                    with open(f"{file}.error.log", "w") as errfile:
                        if stdout:
                            errfile.write(stdout.decode())
                        if stderr:
                            errfile.write(stderr.decode())
                else:
                    print("Minor problems detected.")
        else:
            print("File OK.")


        process.wait()

if __name__ == "__main__":
    files = sys.argv[1:]
    # files = ["a.mkv"]
    check_video(files)

Solution 2:

        with subprocess.Popen(command_line,
                              stdout=subprocess.PIPE,
                              stderr=subprocess.STDOUT,
                              universal_newlines=True) as self.process:

            for line in self.process.stdout:
                print(line, end='')

        return_code = self.process.wait()

From here, you can do whatever you like with each line, like checking for error keywords in them. I think ffmpeg has some standard of error reporting (https://ffmpeg.org/doxygen/trunk/group__lavu__error.html). With this solution, output will be displayed to you same as with directly running ffmpeg. Source: https://stackoverflow.com/a/4417735/1793606. Tested with Python 3.10

Solution 3: Also, you can set err_detect for ffmpeg itself, that should reflect in the return code

HCLivess
  • 1,015
  • 1
  • 13
  • 21