X-Git-Url: https://git.squeep.com/?a=blobdiff_plain;ds=sidebyside;f=lib%2Fpleroma%2Fhelpers%2Fmedia_helper.ex;h=738adfcaa9d446e71dafc5aa7ab2b169dbf934dd;hb=d7262f7d2232343e47c2206b134a7d794e35c505;hp=3256802a043eed23e869e4e3ca182a1a90be6b1a;hpb=2cfe2dc81b82f0ab30d82763f2874010966acae6;p=akkoma
diff --git a/lib/pleroma/helpers/media_helper.ex b/lib/pleroma/helpers/media_helper.ex
index 3256802a0..738adfcaa 100644
--- a/lib/pleroma/helpers/media_helper.ex
+++ b/lib/pleroma/helpers/media_helper.ex
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors
+# Copyright © 2017-2021 Pleroma Authors
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Helpers.MediaHelper do
@@ -7,15 +7,26 @@ defmodule Pleroma.Helpers.MediaHelper do
Handles common media-related operations.
"""
- @tmp_base "/tmp/pleroma-media_preview-pipe"
+ alias Pleroma.HTTP
+
+ require Logger
+
+ def missing_dependencies do
+ Enum.reduce([imagemagick: "convert", ffmpeg: "ffmpeg"], [], fn {sym, executable}, acc ->
+ if Pleroma.Utils.command_available?(executable) do
+ acc
+ else
+ [sym | acc]
+ end
+ end)
+ end
def image_resize(url, options) do
with executable when is_binary(executable) <- System.find_executable("convert"),
- {:ok, args} <- prepare_resize_args(options),
- url = Pleroma.Web.MediaProxy.url(url),
- {:ok, env} <- Pleroma.HTTP.get(url),
- {:ok, fifo_path} <- mkfifo()
- do
+ {:ok, args} <- prepare_image_resize_args(options),
+ {:ok, env} <- HTTP.get(url, [], pool: :media),
+ {:ok, fifo_path} <- mkfifo() do
+ args = List.flatten([fifo_path, args])
run_fifo(fifo_path, env, executable, args)
else
nil -> {:error, {:convert, :command_not_found}}
@@ -23,36 +34,93 @@ defmodule Pleroma.Helpers.MediaHelper do
end
end
- defp prepare_resize_args(%{max_width: max_width, max_height: max_height} = options) do
+ defp prepare_image_resize_args(
+ %{max_width: max_width, max_height: max_height, format: "png"} = options
+ ) do
+ quality = options[:quality] || 85
+ resize = Enum.join([max_width, "x", max_height, ">"])
+
+ args = [
+ "-resize",
+ resize,
+ "-quality",
+ to_string(quality),
+ "png:-"
+ ]
+
+ {:ok, args}
+ end
+
+ defp prepare_image_resize_args(%{max_width: max_width, max_height: max_height} = options) do
quality = options[:quality] || 85
resize = Enum.join([max_width, "x", max_height, ">"])
+
args = [
- "-interlace", "Plane",
- "-resize", resize,
- "-quality", to_string(quality)
+ "-interlace",
+ "Plane",
+ "-resize",
+ resize,
+ "-quality",
+ to_string(quality),
+ "jpg:-"
]
+
{:ok, args}
end
- defp prepare_resize_args(_), do: {:error, :missing_options}
+ defp prepare_image_resize_args(_), do: {:error, :missing_options}
+
+ # Note: video thumbnail is intentionally not resized (always has original dimensions)
+ 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",
+ "-i",
+ fifo_path,
+ "-vframes",
+ "1",
+ "-f",
+ "mjpeg",
+ "-loglevel",
+ "error",
+ "-"
+ ] 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, "jpg:-"])
- pid = Port.open({:spawn_executable, executable}, [:use_stdio, :stream, :exit_status, :binary, args: args])
+ 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])
- true = Port.command(fifo, env.body)
+ fix = Pleroma.Helpers.QtFastStart.fix(env.body)
+ true = Port.command(fifo, fix)
:erlang.port_close(fifo)
loop_recv(pid)
after
File.rm(fifo_path)
end
- defp mkfifo() do
- path = "#{@tmp_base}#{to_charlist(:erlang.phash2(self()))}"
+ defp mkfifo do
+ path = Path.join(System.tmp_dir!(), "pleroma-media-preview-pipe-#{Ecto.UUID.generate()}")
+
case System.cmd("mkfifo", [path]) do
{_, 0} ->
spawn(fifo_guard(path))
{:ok, path}
+
{_, err} ->
{:error, {:fifo_failed, err}}
end
@@ -60,8 +128,10 @@ defmodule Pleroma.Helpers.MediaHelper do
defp fifo_guard(path) do
pid = self()
- fn() ->
+
+ fn ->
ref = Process.monitor(pid)
+
receive do
{:DOWN, ^ref, :process, ^pid, _} ->
File.rm(path)
@@ -77,14 +147,16 @@ defmodule Pleroma.Helpers.MediaHelper do
receive do
{^pid, {:data, data}} ->
loop_recv(pid, acc <> data)
+
{^pid, {:exit_status, 0}} ->
{:ok, acc}
+
{^pid, {:exit_status, status}} ->
{:error, status}
- after
- 5000 ->
- :erlang.port_close(pid)
- {:error, :timeout}
+ after
+ 5000 ->
+ :erlang.port_close(pid)
+ {:error, :timeout}
end
end
end