X-Git-Url: http://git.squeep.com/?a=blobdiff_plain;ds=sidebyside;f=lib%2Fpleroma%2Fhelpers%2Fmedia_helper.ex;h=0299b16aec31baa214621fe7127ddb348415598e;hb=697bea04731614bcd2e1e10f0564863dc49a49fa;hp=5fe13558460c72cf6fcad03d4be5671b6c687d2a;hpb=afa03ca8e2cffc85628beb5f9a70401d984ab216;p=akkoma diff --git a/lib/pleroma/helpers/media_helper.ex b/lib/pleroma/helpers/media_helper.ex index 5fe135584..0299b16ae 100644 --- a/lib/pleroma/helpers/media_helper.ex +++ b/lib/pleroma/helpers/media_helper.ex @@ -7,18 +7,67 @@ defmodule Pleroma.Helpers.MediaHelper do Handles common media-related operations. """ - def image_resize(url, %{max_width: max_width, max_height: max_height} = options) do + @tmp_base "/tmp/pleroma-media_preview-pipe" + + def image_resize(url, options) do + with executable when is_binary(executable) <- System.find_executable("convert"), + {:ok, args} <- prepare_image_resize_args(options), + 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, {:convert, :command_not_found}} + {:error, _} = error -> error + end + 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), + "jpg:-" + ] + {:ok, args} + end - cmd = ~s""" - convert - -resize '#{max_width}x#{max_height}>' -quality #{quality} - - """ + defp prepare_image_resize_args(_), do: {:error, :missing_options} - pid = Port.open({:spawn, cmd}, [:use_stdio, :stream, :exit_status, :binary]) - {:ok, env} = url |> Pleroma.Web.MediaProxy.url() |> Pleroma.HTTP.get() - image = env.body - Port.command(pid, image) + 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]) + fifo = Port.open(to_charlist(fifo_path), [:eof, :binary, :stream, :out]) + true = Port.command(fifo, env.body) + :erlang.port_close(fifo) loop_recv(pid) + after + File.rm(fifo_path) + end + + defp mkfifo() do + path = "#{@tmp_base}#{to_charlist(:erlang.phash2(self()))}" + case System.cmd("mkfifo", [path]) do + {_, 0} -> + spawn(fifo_guard(path)) + {:ok, path} + {_, err} -> + {:error, {:fifo_failed, err}} + end + end + + defp fifo_guard(path) do + pid = self() + fn() -> + ref = Process.monitor(pid) + receive do + {:DOWN, ^ref, :process, ^pid, _} -> + File.rm(path) + end + end end defp loop_recv(pid) do @@ -29,12 +78,14 @@ 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} end end end