From ef9d12fcc500d7429bee0d6ccffe3596434aee52 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Thu, 27 Aug 2020 12:31:55 -0500 Subject: [PATCH] Attempt at supporting video thumbnails via ffmpeg --- lib/pleroma/helpers/media_helper.ex | 19 +++++++++++++++++++ .../web/media_proxy/media_proxy_controller.ex | 17 ++++++++++++++--- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/lib/pleroma/helpers/media_helper.ex b/lib/pleroma/helpers/media_helper.ex index 0299b16ae..7e1af8bac 100644 --- a/lib/pleroma/helpers/media_helper.ex +++ b/lib/pleroma/helpers/media_helper.ex @@ -37,6 +37,25 @@ defp prepare_image_resize_args(%{max_width: max_width, max_height: max_height} = defp prepare_image_resize_args(_), do: {:error, :missing_options} + def video_framegrab(url) do + with executable when is_binary(executable) <- System.find_executable("ffmpeg"), + args = [ + "-i", "-", + "-vframes", "1", + "-f", "mjpeg", + "-loglevel", "error", + "-" + ], + url = Pleroma.Web.MediaProxy.url(url), + {:ok, env} <- Pleroma.HTTP.get(url), + {:ok, fifo_path} <- mkfifo() do + run_fifo(fifo_path, env, executable, args) + else + nil -> {:error, {:ffmpeg, :command_not_found}} + {:error, _} = error -> error + end + end + defp run_fifo(fifo_path, env, executable, args) do args = List.flatten([fifo_path, args]) pid = Port.open({:spawn_executable, executable}, [:use_stdio, :stream, :exit_status, :binary, args: args]) diff --git a/lib/pleroma/web/media_proxy/media_proxy_controller.ex b/lib/pleroma/web/media_proxy/media_proxy_controller.ex index 736b7db56..7ac1a97e2 100644 --- a/lib/pleroma/web/media_proxy/media_proxy_controller.ex +++ b/lib/pleroma/web/media_proxy/media_proxy_controller.ex @@ -78,9 +78,7 @@ defp handle_preview("image/" <> _ = _content_type, conn, url) do end defp handle_preview("video/" <> _ = _content_type, conn, url) do - mediaproxy_url = url |> MediaProxy.url() - - redirect(conn, external: mediaproxy_url) + handle_video_preview(conn, url) end defp handle_preview(content_type, conn, _url) do @@ -106,6 +104,19 @@ defp handle_image_preview(%{params: params} = conn, url) do end end + defp handle_video_preview(conn, url) do + with {:ok, thumbnail_binary} <- + MediaHelper.video_framegrab(url) do + conn + |> put_resp_header("content-type", "image/jpeg") + |> put_resp_header("content-disposition", "inline; filename=\"preview.jpg\"") + |> send_resp(200, thumbnail_binary) + else + _ -> + send_resp(conn, :failed_dependency, "Can't handle preview.") + end + end + defp thumbnail_max_dimensions(params) do config = Config.get([:media_preview_proxy], [])