2

I'm trying to replicate the AWS Lambda solution of the following tutorial with Go AWS SDK. My process is a little bit more complicated though because I want to be able to do the following:

  • Convert the video to h265
  • Transpose it to m3u8 (HLS)
  • Upload the h265 video directly from pipe (without local copy)
  • Upload the m3u8 and ts files (apparently impossible to do without local copy, not sure though)

I came up with the following:

func upload(video_name string) {
    var compress_args = []string{
        "-loglevel", "fatal",
        "-i", video_name + ".mp4",
        "-vcodec", "libx265",
        "-x265-params", "log-level=fatal",
        "-crf", "28",
        "-f", "mp4",
        "-movflags", "frag_keyframe+empty_moov",
        "-", // pipes output to stdout
    }
    var transpose_args = []string{
        "-loglevel", "fatal",
        "-i", "-", // Read input from stdin
        "-vcodec", "libx265",
        "-x265-params", "log-level=fatal",
        "-crf", "28",
        "-start_number", "0",
        "-hls_time", "1",
        "-hls_list_size", "0",
        "-f", "hls", "tmp/" + video_name + ".m3u8",
    }

    cmd := exec.Command("ffmpeg", compress_args...)
    cmd2 := exec.Command("tee", "new_" + video_name + ".mp4") // how to improve that ?
    cmd3 := exec.Command("ffmpeg", transpose_args...)

    cmd.Stderr = os.Stderr
    cmd2.Stderr = os.Stderr
    cmd3.Stderr = os.Stderr

    cmd2.Stdin, _ = cmd.StdoutPipe()
    cmd3.Stdin, _ = cmd2.StdoutPipe()
    cmd3.Stdout = os.Stdout

    cmd.Start()
    cmd2.Start()
    cmd3.Start()
    cmd.Wait()
    cmd2.Wait()
    cmd3.Wait()
}

For now, what this does is that it pipes the compression, the tee and the transpose commands. The tee creates a local copy of the .mp4 and relay to the compression command. Now, I would like to be able to pass tee's output to the Body parameter for s3.PutObjectInput.

Should I use a Named Pipe, let tee write on it and then somehow pass that to the PutObjectInput? is it even possible? what are the other possibilities ?

Edit

I made the compressed file upload work by using named pipes and not waiting for the commands to finish (original idea). Here is the new code:

func upload(video_name string) {
    // ARGS

    syscall.Mkfifo("pipe", 0644)

    // CMDS and STDOUT/STDIN redirections 

    named_pipe, _ := os.OpenFile("pipe", os.O_RDONLY|syscall.O_NONBLOCK, 0600)
    defer named_pipe.Close()
    syscall.SetNonblock(int(named_pipe.Fd()), false)

    sess := session.Must(session.NewSession(&aws.Config{
        Region: aws.String(region),
    }))
    uploader := s3manager.NewUploader(sess, func(u *s3manager.Uploader) {
        u.PartSize = 5 * 1024 * 1024 // 5MB
    })

    compress_cmd.Start()
    tee_cmd.Start()
    transpose_cmd.Start()

    _, err := uploader.UploadWithContext(context.Background(), &s3manager.UploadInput{
        Bucket: aws.String(bucket),
        Key:    aws.String(video_name + ".mp4"),
        Body:   &reader{named_pipe},
    })
}

where reader is:

type reader struct {
    r io.Reader
}

func (r *reader) Read(p []byte) (int, error) {
    return r.r.Read(p)
}

However, is there a way to wait for the whole process to finish before uploading the HLS output?

I tried waiting for transpose_cmd to finish after the UploadWithContext but this makes the Uploader quit prematurely.

Clément Jean
  • 1,735
  • 1
  • 14
  • 32
  • Maybe you could pipe the ffmpeg output to the write, i.e. something like `io.Copy(os.Stdout, out)` – Wolfgang Dec 09 '21 at 10:17
  • the problem is that the [`PutObjectInput`](https://docs.aws.amazon.com/sdk-for-go/api/service/s3/#PutObjectInput) accepts a io.ReadSeeker and I don't know how to pass tee's output to that – Clément Jean Dec 09 '21 at 10:26
  • 1
    Possible duplicates: https://stackoverflow.com/questions/43595911/how-to-save-data-streams-in-s3-aws-sdk-go-example-not-working, https://stackoverflow.com/questions/34177137/stream-file-upload-to-aws-s3-using-go – Tom Dec 09 '21 at 13:14
  • 1
    @Tom the answers look indeed pretty interesting however none of them use the Pipe method and I would like guidance on how to redirect tee's output to the uploader mentioned – Clément Jean Dec 09 '21 at 13:18
  • 1
    @ClémentJean Makes sense. Thought I include them for the sake of completeness :) Does this qa help you?: https://stackoverflow.com/a/37735325/5779083 – Tom Dec 09 '21 at 13:30
  • @Tom will try and keep this post updated – Clément Jean Dec 09 '21 at 14:00

0 Answers0