summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Tashkinov <ivantashkinov@gmail.com>2020-09-14 21:50:59 +0300
committerIvan Tashkinov <ivantashkinov@gmail.com>2020-09-14 21:50:59 +0300
commitd52eece03ab744fa7c18bbdf70e20b5bd9589f13 (patch)
treed0aaf620891d7ef42b258a68c0fa860f3a7a194a
parentcd234a5321b9d33146b90be95d84fa67aa4f7707 (diff)
[#2497] Prototype of video streaming for media preview proxy (WIP).
-rw-r--r--lib/pleroma/helpers/media_helper.ex58
1 files changed, 56 insertions, 2 deletions
diff --git a/lib/pleroma/helpers/media_helper.ex b/lib/pleroma/helpers/media_helper.ex
index d834b4a07..0183a8625 100644
--- a/lib/pleroma/helpers/media_helper.ex
+++ b/lib/pleroma/helpers/media_helper.ex
@@ -8,6 +8,7 @@ defmodule Pleroma.Helpers.MediaHelper do
"""
alias Pleroma.HTTP
+ alias Pleroma.ReverseProxy
@tmp_base "/tmp/pleroma-media_preview-pipe"
@@ -62,7 +63,6 @@ defmodule Pleroma.Helpers.MediaHelper do
def video_framegrab(url) do
with executable when is_binary(executable) <- System.find_executable("ffmpeg"),
- {:ok, env} <- HTTP.get(url, [], pool: :media),
{:ok, fifo_path} <- mkfifo(),
args = [
"-y",
@@ -76,13 +76,66 @@ defmodule Pleroma.Helpers.MediaHelper do
"error",
"-"
] do
- run_fifo(fifo_path, env, executable, args)
+ stream_through_fifo(url, fifo_path, executable, args)
else
nil -> {:error, {:ffmpeg, :command_not_found}}
{:error, _} = error -> error
end
end
+ defp stream_loop(http_client, fifo, ffmpeg_pid) do
+ case ReverseProxy.Client.stream_body(http_client) do
+ :done ->
+ # Edge case (ffmpeg has not started processing partial input)
+ close_http_client(http_client)
+ loop_recv(ffmpeg_pid)
+
+ {:ok, data, http_client} ->
+ # Will be true if port is alive, not busy, and has received the input
+ command_sent =
+ try do
+ Port.command(fifo, data, [:nosuspend])
+ rescue
+ _ -> false
+ end
+
+ if command_sent do
+ stream_loop(http_client, fifo, ffmpeg_pid)
+ else
+ close_http_client(http_client)
+ loop_recv(ffmpeg_pid)
+ end
+
+ {:error, error} ->
+ {:error, error}
+ end
+ end
+
+ defp close_http_client(http_client) do
+ ReverseProxy.Client.close(http_client)
+ end
+
+ defp stream_through_fifo(url, fifo_path, executable, args) do
+ ffmpeg_pid =
+ Port.open({:spawn_executable, executable}, [
+ :use_stdio,
+ :stream,
+ :exit_status,
+ :binary,
+ args: args
+ ])
+
+ fifo = Port.open(to_charlist(fifo_path), [:eof, :binary, :stream, :out])
+ Process.unlink(fifo)
+
+ with {:ok, code, _headers, client} when code in 200..299 <-
+ ReverseProxy.Client.request(:get, url, [], "", pool: :media) do
+ stream_loop(client, fifo, ffmpeg_pid)
+ end
+ after
+ File.rm(fifo_path)
+ end
+
defp run_fifo(fifo_path, env, executable, args) do
pid =
Port.open({:spawn_executable, executable}, [
@@ -94,6 +147,7 @@ defmodule Pleroma.Helpers.MediaHelper do
])
fifo = Port.open(to_charlist(fifo_path), [:eof, :binary, :stream, :out])
+
fix = Pleroma.Helpers.QtFastStart.fix(env.body)
true = Port.command(fifo, fix)
:erlang.port_close(fifo)