Kelly Flet
Kelly Flet

Reputation: 564

Get frame from video bytes

I'm extracting a frame from a video using ffmpeg and golang. If I have a video in bytes instead of saved on disk as an .mp4, how do I tell ffmpeg to read from those bytes without having to write the file to disk, as that is much slower?

I have this working reading from a file, but I'm not sure how to read from bytes.

I've looked at the ffmpeg documentation here but only see output examples instead of input examples.

func ExtractImage(fileBytes []byte){

    // command line args, path, and command
    command = "ffmpeg"
    frameExtractionTime := "0:00:05.000"
    vframes := "1"
    qv := "2"
    output := "/home/ubuntu/media/video-to-image/output-" + time.Now().Format(time.Kitchen) + ".jpg"

    // TODO: use fileBytes instead of videoPath
    // create the command
    cmd := exec.Command(command,
        "-ss", frameExtractionTime,
        "-i", videoPath,
        "-vframes", vframes,
        "-q:v", qv,
        output)

    // run the command and don't wait for it to finish. waiting exec is run
    // ignore errors for examples-sake
    _ = cmd.Start()
    _ = cmd.Wait()
}

Upvotes: 2

Views: 2817

Answers (1)

ConnectionLost
ConnectionLost

Reputation: 772

You can make ffmpeg to read data from stdin rather than reading file from disk, by specifying - as the value of the option -i. Then just pass your video bytes as stdin to the command.

func ExtractImage(fileBytes []byte){

    // command line args, path, and command
    command := "ffmpeg"
    frameExtractionTime := "0:00:05.000"
    vframes := "1"
    qv := "2"
    output := "/home/ubuntu/media/video-to-image/output-" + time.Now().Format(time.Kitchen) + ".jpg"

    cmd := exec.Command(command,
        "-ss", frameExtractionTime,
        "-i", "-",  // to read from stdin
        "-vframes", vframes,
        "-q:v", qv,
        output)

    cmd.Stdin = bytes.NewBuffer(fileBytes)

    // run the command and don't wait for it to finish. waiting exec is run
    // ignore errors for examples-sake
    _ = cmd.Start()
    _ = cmd.Wait()
}

You may need to run ffmpeg -protocols to determine if the pipe protocol (to read from stdin) is supported in your build of ffmpeg.

Upvotes: 6

Related Questions