ndrean

ndrean

Can't make erlexec work with stdin as input

I want to transform programmatically an image with FFmpeg. I know you have nice libraries Image, Vix, Stb_image but I want to use the capacity of FFmpeg to take buffer as input. I don’t see how System.cmd nor Port can accept inputs from stdin so I sought for something.

I found Porcelain and erlexec. I saw the last commit was 4 years ago for Porcelaine. Not saying it’s bad but erlexec has its last commit 2 months ago.

I can do it with Porcelaine but not with erlexec and I don’t see why. Maybe someone has some experience with it.

file = File.read!("img.png")

porcelaine = Porcelain.spawn("ffmpeg", ["-i", "-", "img.jpg"], in: :receive, out: :stream)
 {:input, data} = Porcelain.Process.send_input(porcelaine, file)
File.write!("img.jpg", file)
#=> success

but not erlexec: “bad arguments”.

{:ok, pid, os_pid} = :exec.run("ffmpeg -i - img.jpg", [:stdin, stdout: "img2.jpg"])
 :ok = :exec.send(os_pid, file)

[error] GenServer :exec terminating
** (stop) :einval
Last message: {:EXIT, #Port<0.6>, :einval}

Is it related to the way you pass strings to the function?

Marked As Solved

saleyn

saleyn

I see. The issue is that ffmpeg needs to know that the input sent to it is complete. Otherwise, it’ll sit waiting for more data.

When you use pipes in the shell, the head of the pipe (cat img.png) closes the pipe upon sending the entire content of the file, which helps ffmpeg detect the eof.

In case of erlexec you need to tell the child process that there’s an eof condition like this:

> f = File.read!("test.png")
> {:ok, _, i} = :exec.run_link("ffmpeg -y -i - img.jpg", [:stdin, :stderr])
> :exec.send(i, f)
> :exec.send(i, :eof)
> flush       # This will print out the output of ffmpeg written to stderr and sent to the caller's terminal

This will fix your issue.

It is illustrated here.

Also Liked

akash-akya

akash-akya

@ndrean I created Exile & ExCmd specifically to support moving large amount of data between external process. If you are interested you can check them out.

I created a Livebook sometime back using ffmpeg : Community Livebooks Thread - Share Yours! - #4 by akash-akya

Last Post!

ndrean

ndrean

Looks nice! Many thanks!
I did not found ex_cmd, more Elixir style.
I will look more closely when I find why System.find_executable("ffmepg") returns nil ! (Livebook only).

I solved my problem with Porcelain by using a GenServer. The use case is receiving chunks as strings via a WebSocket. In the GenServer, I spawn Porcelain to start FFmpeg to read from stdin, and then just forward messages/chunks continuously to the GenServer and Porcelain feeds pipe:0.

I see you request files via a GET request, but in my case I want to receive octet-stream via HTTP and am stuck so I will definitively look more closely.

Where Next?

Popular in Questions Top

nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New
Lily
In templates/appointment/index.html.eex: &lt;%= for appointment &lt;- @appointments do %&gt; &lt;tr&gt; &lt;td&gt;&lt;%= appoi...
New
sen
Hi All, I set a environment variables in dev.exs , like below code. when i start server, how can i set the ${enable} value? thanks. d...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New

Other popular topics Top

vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
Darmani72
If I have a post route which an argument: post /my_post_route/:my_param1, MyController.my_post_handler How would get the post params ...
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
greenz1
I have a phoenix application from which a user can download multiple(5-6) files of size 1MB. I couldn’t find anything related to sending ...
New
sen
Hi All, I set a environment variables in dev.exs , like below code. when i start server, how can i set the ${enable} value? thanks. d...
New
dblack
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar. I p...
New

We're in Beta

About us Mission Statement