Attempt at supporting video thumbnails via ffmpeg
authorMark Felder <feld@FreeBSD.org>
Thu, 27 Aug 2020 17:31:55 +0000 (12:31 -0500)
committerMark Felder <feld@FreeBSD.org>
Thu, 27 Aug 2020 17:31:55 +0000 (12:31 -0500)
lib/pleroma/helpers/media_helper.ex
lib/pleroma/web/media_proxy/media_proxy_controller.ex

index 0299b16aec31baa214621fe7127ddb348415598e..7e1af8bacf8d5af1750c6150cffcf84544e3f042 100644 (file)
@@ -37,6 +37,25 @@ defmodule Pleroma.Helpers.MediaHelper do
 
   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])
index 736b7db56364fd68246e52aea1ac1111bea0913b..7ac1a97e2edf20d42f686c223aaee6825bf7087a 100644 (file)
@@ -78,9 +78,7 @@ defmodule Pleroma.Web.MediaProxy.MediaProxyController 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 @@ defmodule Pleroma.Web.MediaProxy.MediaProxyController 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], [])