mirror of
https://github.com/philomena-dev/philomena.git
synced 2025-01-19 22:27:59 +01:00
Merge pull request #388 from philomena-dev/transparency-fixes
Fix transparency issues in webm videos
This commit is contained in:
commit
0a48359ddc
2 changed files with 68 additions and 17 deletions
|
@ -13,6 +13,9 @@ defmodule PhilomenaMedia.GifPreview do
|
|||
target_framerate: target_framerate()
|
||||
]
|
||||
|
||||
@typedoc "One of av1, h264, libvpx, libvpx-vp9"
|
||||
@type decoder :: String.t()
|
||||
|
||||
@doc """
|
||||
Generate a GIF preview of the given video input with evenly-spaced sample points.
|
||||
|
||||
|
@ -31,8 +34,8 @@ defmodule PhilomenaMedia.GifPreview do
|
|||
* 1 or above: 5 images
|
||||
* otherwise: 2 images
|
||||
"""
|
||||
@spec preview(Path.t(), Path.t(), duration(), dimensions(), opts()) :: :ok
|
||||
def preview(video, gif, duration, dimensions, opts \\ []) do
|
||||
@spec preview(decoder(), Path.t(), Path.t(), duration(), dimensions(), opts()) :: :ok
|
||||
def preview(decoder, video, gif, duration, dimensions, opts \\ []) do
|
||||
target_framerate = Keyword.get(opts, :target_framerate, 2)
|
||||
|
||||
num_images =
|
||||
|
@ -48,22 +51,41 @@ defmodule PhilomenaMedia.GifPreview do
|
|||
{_output, 0} =
|
||||
System.cmd(
|
||||
"ffmpeg",
|
||||
commands(video, gif, clamp(duration), dimensions, num_images, target_framerate)
|
||||
commands(decoder, video, gif, clamp(duration), dimensions, num_images, target_framerate)
|
||||
)
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
@spec commands(Path.t(), Path.t(), duration(), dimensions(), num_images(), target_framerate()) ::
|
||||
@spec commands(
|
||||
decoder(),
|
||||
Path.t(),
|
||||
Path.t(),
|
||||
duration(),
|
||||
dimensions(),
|
||||
num_images(),
|
||||
target_framerate()
|
||||
) ::
|
||||
[String.t()]
|
||||
defp commands(video, gif, duration, {target_width, target_height}, num_images, target_framerate) do
|
||||
defp commands(
|
||||
decoder,
|
||||
video,
|
||||
gif,
|
||||
duration,
|
||||
{target_width, target_height},
|
||||
num_images,
|
||||
target_framerate
|
||||
) do
|
||||
# Compute range [0, num_images)
|
||||
image_range = 0..(num_images - 1)
|
||||
|
||||
# Generate input list in the following form:
|
||||
# -ss 0.0 -i input.webm
|
||||
# -ss 0.0 -c:v libvpx -i input.webm
|
||||
input_arguments =
|
||||
Enum.flat_map(image_range, &["-ss", "#{&1 * duration / num_images}", "-i", video])
|
||||
Enum.flat_map(
|
||||
image_range,
|
||||
&["-ss", "#{&1 * duration / num_images}", "-c:v", decoder, "-i", video]
|
||||
)
|
||||
|
||||
# Generate graph in the following form:
|
||||
# [0:v] trim=end_frame=1 [t0]; [1:v] trim=end_frame=1 [t1] ...
|
||||
|
@ -87,7 +109,7 @@ defmodule PhilomenaMedia.GifPreview do
|
|||
"[s0] palettegen=stats_mode=single:max_colors=255:reserve_transparent=1 [palettegen]"
|
||||
|
||||
paletteuse_filter =
|
||||
"[s1][palettegen] paletteuse=dither=bayer:bayer_scale=5:new=1:alpha_threshold=255"
|
||||
"[s1][palettegen] paletteuse=dither=bayer:bayer_scale=5:new=1:alpha_threshold=251"
|
||||
|
||||
filter_graph =
|
||||
[
|
||||
|
|
|
@ -29,11 +29,12 @@ defmodule PhilomenaMedia.Processors.Webm do
|
|||
duration = analysis.duration
|
||||
stripped = strip(file)
|
||||
preview = preview(duration, stripped)
|
||||
mp4 = scale_mp4_only(stripped, dimensions, dimensions)
|
||||
decoder = select_decoder(file)
|
||||
mp4 = scale_mp4_only(decoder, stripped, dimensions, dimensions)
|
||||
|
||||
{:ok, intensities} = Intensities.file(preview)
|
||||
|
||||
scaled = Enum.flat_map(versions, &scale(stripped, duration, dimensions, &1))
|
||||
scaled = Enum.flat_map(versions, &scale(decoder, stripped, duration, dimensions, &1))
|
||||
mp4 = [{:copy, mp4, "full.mp4"}]
|
||||
|
||||
[
|
||||
|
@ -82,12 +83,12 @@ defmodule PhilomenaMedia.Processors.Webm do
|
|||
stripped
|
||||
end
|
||||
|
||||
defp scale(file, duration, dimensions, {thumb_name, target_dimensions}) do
|
||||
{webm, mp4} = scale_videos(file, dimensions, target_dimensions)
|
||||
defp scale(decoder, file, duration, dimensions, {thumb_name, target_dimensions}) do
|
||||
{webm, mp4} = scale_videos(decoder, file, dimensions, target_dimensions)
|
||||
|
||||
cond do
|
||||
thumb_name in [:thumb, :thumb_small, :thumb_tiny] ->
|
||||
gif = scale_gif(file, duration, dimensions, target_dimensions)
|
||||
gif = scale_gif(decoder, file, duration, dimensions, target_dimensions)
|
||||
|
||||
[
|
||||
{:copy, webm, "#{thumb_name}.webm"},
|
||||
|
@ -103,7 +104,7 @@ defmodule PhilomenaMedia.Processors.Webm do
|
|||
end
|
||||
end
|
||||
|
||||
defp scale_videos(file, dimensions, target_dimensions) do
|
||||
defp scale_videos(decoder, file, dimensions, target_dimensions) do
|
||||
filter = scale_filter(dimensions, target_dimensions)
|
||||
webm = Briefly.create!(extname: ".webm")
|
||||
mp4 = Briefly.create!(extname: ".mp4")
|
||||
|
@ -113,6 +114,8 @@ defmodule PhilomenaMedia.Processors.Webm do
|
|||
"-loglevel",
|
||||
"0",
|
||||
"-y",
|
||||
"-c:v",
|
||||
decoder,
|
||||
"-i",
|
||||
file,
|
||||
"-c:v",
|
||||
|
@ -162,7 +165,7 @@ defmodule PhilomenaMedia.Processors.Webm do
|
|||
{webm, mp4}
|
||||
end
|
||||
|
||||
defp scale_mp4_only(file, dimensions, target_dimensions) do
|
||||
defp scale_mp4_only(decoder, file, dimensions, target_dimensions) do
|
||||
filter = scale_filter(dimensions, target_dimensions)
|
||||
mp4 = Briefly.create!(extname: ".mp4")
|
||||
|
||||
|
@ -171,6 +174,8 @@ defmodule PhilomenaMedia.Processors.Webm do
|
|||
"-loglevel",
|
||||
"0",
|
||||
"-y",
|
||||
"-c:v",
|
||||
decoder,
|
||||
"-i",
|
||||
file,
|
||||
"-c:v",
|
||||
|
@ -197,15 +202,39 @@ defmodule PhilomenaMedia.Processors.Webm do
|
|||
mp4
|
||||
end
|
||||
|
||||
defp scale_gif(file, duration, dimensions, target_dimensions) do
|
||||
defp scale_gif(decoder, file, duration, dimensions, target_dimensions) do
|
||||
{width, height} = box_dimensions(dimensions, target_dimensions)
|
||||
gif = Briefly.create!(extname: ".gif")
|
||||
|
||||
GifPreview.preview(file, gif, duration, {width, height})
|
||||
GifPreview.preview(decoder, file, gif, duration, {width, height})
|
||||
|
||||
gif
|
||||
end
|
||||
|
||||
defp select_decoder(file) do
|
||||
{output, 0} =
|
||||
System.cmd("ffprobe", [
|
||||
"-loglevel",
|
||||
"0",
|
||||
"-select_streams",
|
||||
"v:0",
|
||||
"-show_entries",
|
||||
"stream=codec_name",
|
||||
"-of",
|
||||
"default=noprint_wrappers=1:nokey=1",
|
||||
"-i",
|
||||
file
|
||||
])
|
||||
|
||||
# Mediatools verifies that we only have one video stream and that it is
|
||||
# one of the supported formats, so the following is safe to do:
|
||||
case output do
|
||||
"vp8\n" -> "libvpx"
|
||||
"vp9\n" -> "libvpx-vp9"
|
||||
"av1\n" -> "av1"
|
||||
end
|
||||
end
|
||||
|
||||
defp scale_filter(dimensions, target_dimensions) do
|
||||
{width, height} = box_dimensions(dimensions, target_dimensions)
|
||||
"scale=w=#{width}:h=#{height},setsar=1"
|
||||
|
|
Loading…
Reference in a new issue