Fork of Pleroma with site-specific changes and feature branches https://git.pleroma.social/pleroma/pleroma
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

84 lines
2.1KB

  1. # Pleroma: A lightweight social networking server
  2. # Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
  3. # SPDX-License-Identifier: AGPL-3.0-only
  4. defmodule Pleroma.Upload.Filter.AnalyzeMetadata do
  5. @moduledoc """
  6. Extracts metadata about the upload, such as width/height
  7. """
  8. require Logger
  9. @behaviour Pleroma.Upload.Filter
  10. @spec filter(Pleroma.Upload.t()) ::
  11. {:ok, :filtered, Pleroma.Upload.t()} | {:ok, :noop} | {:error, String.t()}
  12. def filter(%Pleroma.Upload{tempfile: file, content_type: "image" <> _} = upload) do
  13. try do
  14. image =
  15. file
  16. |> Mogrify.open()
  17. |> Mogrify.verbose()
  18. upload =
  19. upload
  20. |> Map.put(:width, image.width)
  21. |> Map.put(:height, image.height)
  22. |> Map.put(:blurhash, get_blurhash(file))
  23. {:ok, :filtered, upload}
  24. rescue
  25. e in ErlangError ->
  26. Logger.warn("#{__MODULE__}: #{inspect(e)}")
  27. {:ok, :noop}
  28. end
  29. end
  30. def filter(%Pleroma.Upload{tempfile: file, content_type: "video" <> _} = upload) do
  31. try do
  32. result = media_dimensions(file)
  33. upload =
  34. upload
  35. |> Map.put(:width, result.width)
  36. |> Map.put(:height, result.height)
  37. {:ok, :filtered, upload}
  38. rescue
  39. e in ErlangError ->
  40. Logger.warn("#{__MODULE__}: #{inspect(e)}")
  41. {:ok, :noop}
  42. end
  43. end
  44. def filter(_), do: {:ok, :noop}
  45. defp get_blurhash(file) do
  46. with {:ok, blurhash} <- :eblurhash.magick(file) do
  47. blurhash
  48. else
  49. _ -> nil
  50. end
  51. end
  52. defp media_dimensions(file) do
  53. with executable when is_binary(executable) <- System.find_executable("ffprobe"),
  54. args = [
  55. "-v",
  56. "error",
  57. "-show_entries",
  58. "stream=width,height",
  59. "-of",
  60. "csv=p=0:s=x",
  61. file
  62. ],
  63. {result, 0} <- System.cmd(executable, args),
  64. [width, height] <-
  65. String.split(String.trim(result), "x") |> Enum.map(&String.to_integer(&1)) do
  66. %{width: width, height: height}
  67. else
  68. nil -> {:error, {:ffprobe, :command_not_found}}
  69. {:error, _} = error -> error
  70. end
  71. end
  72. end