0

Hello I have the following poc to develop

Given two S3 paths, origin and destination, I need to download from origin apply a conversion and upload to destination.

The idea is not to use a temporary local folder and use stream data ur another better option if you know.

In order to do this I have the following code:

import ffmpeg
import boto3
from io import BytesIO

origin = 'ah/a.mkv'
destination = 'av/a.mp4'

s3_client = boto3.client('s3')

f = BytesIO()
s3_client.download_fileobj('bucket', origin, f)

stream = ffmpeg.input(f)
stream = ffmpeg.output(stream, 'a.mp4', codec='copy')

(stream.run())

The problem is that

Input doesn' this library looks like that this operation is not possible.

https://kkroening.github.io/ffmpeg-python/

TypeError: expected str, bytes or os.PathLike object, not _io.BytesIO

But when another library like

https://github.com/aminyazdanpanah/python-ffmpeg-video-streaming#opening-a-resource

I don't know how do the conversion too.

So do you know any way of do this?

Thanks

Tlaloc-ES
  • 4,825
  • 7
  • 38
  • 84
  • `BytesIO` is not a file-like stream (no `fileno` attribute) thus cannot be piped to/from a subprocess. You need to look for whether `s3_client` can provide such stream. If it can, you can try the `ffmpeg-python` with it, but you may need to call `subprocess.run` yourself if the package doesn't recognize the stream as pipable. – kesh May 03 '22 at 14:20
  • BytesIO. has getBuffer, that I guess is a file-like, so the anotehr questios is how can I use that in subprocess.run? – Tlaloc-ES May 03 '22 at 14:58
  • No, as I said above, a python I/O stream to be a "file-like" (not 100% if that's the exact term) it must have `fileno` attribute, which essentially is an INT file identifier assigned by the OS (not python). `BytesIO` does not have it. – kesh May 03 '22 at 15:01
  • Now, your comment also reminded me that you can pass the buffer to the subprocess by passing `input=f.getbuffer()` argument in `sp.run()` call. Don't know how that works with `ffmpeg-python`. It's `run()` counterpart (wrapper) may allow `input` argument as well. – kesh May 03 '22 at 15:03
  • The for example with this ```subprocess.run(['ffmpeg', "-codec copy", "aaa.mp4"], input=f.getbuffer())``` how I set the input as a parameter? – Tlaloc-ES May 03 '22 at 15:07
  • Yep, give that a try. – kesh May 03 '22 at 15:22
  • Now I need know how get the output in the answer, thanks for your answer! – Tlaloc-ES May 03 '22 at 15:50

1 Answers1

3

Finnaly the library works with

s3_client = boto3.client('s3')

f = BytesIO()
s3_client.download_fileobj('bucket', 'path', f)

process = (
    ffmpeg
    .input('pipe:') \
    .output('aa.mp4') \
    .overwrite_output() \
    .run_async(pipe_stdin=True) \
)

process.communicate(input=f.getbuffer())
Tlaloc-ES
  • 4,825
  • 7
  • 38
  • 84