Pleroma/lib/pleroma/upload/filter/analyze_metadata.ex

84 lines
2.1 KiB
Elixir

# Pleroma: A lightweight social networking server
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Upload.Filter.AnalyzeMetadata do
@moduledoc """
Extracts metadata about the upload, such as width/height
"""
require Logger
@behaviour Pleroma.Upload.Filter
@spec filter(Pleroma.Upload.t()) ::
{:ok, :filtered, Pleroma.Upload.t()} | {:ok, :noop} | {:error, String.t()}
def filter(%Pleroma.Upload{tempfile: file, content_type: "image" <> _} = upload) do
try do
image =
file
|> Mogrify.open()
|> Mogrify.verbose()
upload =
upload
|> Map.put(:width, image.width)
|> Map.put(:height, image.height)
|> Map.put(:blurhash, get_blurhash(file))
{:ok, :filtered, upload}
rescue
e in ErlangError ->
Logger.warn("#{__MODULE__}: #{inspect(e)}")
{:ok, :noop}
end
end
def filter(%Pleroma.Upload{tempfile: file, content_type: "video" <> _} = upload) do
try do
result = media_dimensions(file)
upload =
upload
|> Map.put(:width, result.width)
|> Map.put(:height, result.height)
{:ok, :filtered, upload}
rescue
e in ErlangError ->
Logger.warn("#{__MODULE__}: #{inspect(e)}")
{:ok, :noop}
end
end
def filter(_), do: {:ok, :noop}
defp get_blurhash(file) do
with {:ok, blurhash} <- :eblurhash.magick(file) do
blurhash
else
_ -> nil
end
end
defp media_dimensions(file) do
with executable when is_binary(executable) <- System.find_executable("ffprobe"),
args = [
"-v",
"error",
"-show_entries",
"stream=width,height",
"-of",
"csv=p=0:s=x",
file
],
{result, 0} <- System.cmd(executable, args),
[width, height] <-
String.split(String.trim(result), "x") |> Enum.map(&String.to_integer(&1)) do
%{width: width, height: height}
else
nil -> {:error, {:ffprobe, :command_not_found}}
{:error, _} = error -> error
end
end
end