Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

(Go) FFmpeg stdout produces a jumbled mess of plain text mixed with binary

I’m trying to pipe r.Body into ffmpeg as it’s stdin, then pipe stdout as the http response.

On the client, I am sending the data via POST from an html form, then creating a blob for the response and prompting the browser to download it:

<script>
        document.getElementById('uploadForm').addEventListener('submit', function (event) {
            event.preventDefault();

            const fileInput = document.getElementById('file');
            const file = fileInput.files[0];

            const formData = new FormData();
            formData.append('file', file);

            fetch('/http', {
                method: 'POST',
                body: file,
                headers: {
                    'Content-Type': file.type,
                }
            })
                .then(response => {
                    const blob = response.blob();
                    const url = window.URL.createObjectURL(blob);
                    const a = document.createElement('a');
                    a.style.display = 'none';
                    a.href = url;
                    a.download = 'output.flv';
                    document.body.appendChild(a);
                    a.click();
                    window.URL.revokeObjectURL(url);
                })
                .catch(error => console.error(error));
        });
    </script>

On the server, I am creating an *exec.Cmd, assigning r.Body to it’s stdin, and assigning w to both it’s stdout and stderr:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

func handleHTTP(w http.ResponseWriter, r *http.Request) {
    command := "ffmpeg -f mp4 -i - -vf scale=100:50 -c:a copy -c:v libx264 -f flv pipe:1"
    ffmpegCmd := PrepareCommand(command, r.Body, w, w)

    // Run FFmpeg command
    if err := ffmpegCmd.Run(); err != nil {
        http.Error(w, fmt.Sprintf("FFmpeg command failed: %v", err), http.StatusInternalServerError)
    }
}

func PrepareCommand(command string, stdin io.ReadCloser, stdout io.Writer, stderr io.Writer) *exec.Cmd {
    command = strings.TrimSpace(command)
    name, args := FormatCommand(command)
    ffmpegCmd := exec.Command(name, args...)
    ffmpegCmd.Stdin = stdin
    ffmpegCmd.Stdout = stdout
    ffmpegCmd.Stderr = stderr
    return ffmpegCmd
}

func FormatCommand(str string) (name string, args []string) {
    parts := strings.Split(str, " ")
    return parts[0], parts[1:]
}

When viewed in a text editor, the output file consists of the plain text emitted from stdout when the command starts and the binary data mixed together:

Part 1/3
Part 2/3
Part 3/3

Does anyone know how to get rid of the plain text output before piping the data into stdin? Thanks.

The output file should not contain plain text from the command start-up.

>Solution :

In the line:

ffmpegCmd := PrepareCommand(command, r.Body, w, w)

…change the last argument (indicating where stderr — which is properly used for logs, status messages, prompts, and other "diagnostic" content intended for human operators — is redirected) to somewhere that doesn’t get mixed with output intended for programmatic consumption:

ffmpegCmd := PrepareCommand(command, r.Body, w, os.Stderr)
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading