Generate PNG with proper theme and scale

integrate-vt
Marcin Kulik 7 years ago
parent c6ab74a879
commit 13223d690c

@ -1,10 +1,11 @@
defmodule Asciinema.PngGenerator do
alias Asciinema.Asciicast
alias Asciinema.PngGenerator.PngParams
@doc "Generates PNG image from asciicast and returns path to it"
@callback generate(asciicast :: %Asciicast{}) :: {:ok, String.t} | {:error, term}
@callback generate(asciicast :: %Asciicast{}, png_params :: %PngParams{}) :: {:ok, String.t} | {:error, term}
def generate(asciicast) do
Application.get_env(:asciinema, :png_generator).generate(asciicast)
def generate(asciicast, png_params) do
Application.get_env(:asciinema, :png_generator).generate(asciicast, png_params)
end
end

@ -2,13 +2,14 @@ defmodule Asciinema.PngGenerator.A2png do
@behaviour Asciinema.PngGenerator
use GenServer
alias Asciinema.Asciicast
alias Asciinema.PngGenerator.PngParams
@pool_name :worker
@acquire_timeout 5000
@a2png_timeout 30000
@result_timeout 35000
def generate(%Asciicast{} = asciicast) do
def generate(%Asciicast{} = asciicast, %PngParams{} = png_params) do
{:ok, tmp_dir_path} = Briefly.create(directory: true)
try do
@ -16,7 +17,7 @@ defmodule Asciinema.PngGenerator.A2png do
@pool_name,
(fn pid ->
try do
GenServer.call(pid, {:generate, asciicast, tmp_dir_path}, @result_timeout)
GenServer.call(pid, {:generate, asciicast, png_params, tmp_dir_path}, @result_timeout)
catch
:exit, {:timeout, _} ->
{:error, :timeout}
@ -40,8 +41,8 @@ defmodule Asciinema.PngGenerator.A2png do
{:ok, nil}
end
def handle_call({:generate, asciicast, tmp_dir_path}, _from, state) do
{:reply, do_generate(asciicast, tmp_dir_path), state}
def handle_call({:generate, asciicast, png_params, tmp_dir_path}, _from, state) do
{:reply, do_generate(asciicast, png_params, tmp_dir_path), state}
end
def poolboy_config do
@ -51,15 +52,22 @@ defmodule Asciinema.PngGenerator.A2png do
{:max_overflow, 0}]
end
defp do_generate(asciicast, tmp_dir_path) do
defp do_generate(asciicast, png_params, tmp_dir_path) do
path = Asciicast.json_store_path(asciicast)
json_path = Path.join(tmp_dir_path, "tmp.json")
png_path = Path.join(tmp_dir_path, "tmp.png")
snapshot_at = "#{asciicast.duration / 2}"
args = [
json_path,
png_path,
Float.to_string(png_params.snapshot_at),
png_params.theme,
Integer.to_string(png_params.scale)
]
with {:ok, file} <- file_store().open(path),
{:ok, _} <- :file.copy(file, json_path),
process <- Porcelain.spawn(bin_path(), [json_path, png_path, snapshot_at]),
process <- Porcelain.spawn(bin_path(), args),
{:ok, %{status: 0}} <- Porcelain.Process.await(process, @a2png_timeout) do
{:ok, png_path}
else

@ -0,0 +1,3 @@
defmodule Asciinema.PngGenerator.PngParams do
defstruct [:snapshot_at, :theme, :scale]
end

@ -5,8 +5,10 @@ defmodule Asciinema.AsciicastImageController do
def show(conn, %{"id" => id} = _params) do
asciicast = Repo.one!(Asciicast.by_id_or_secret_token(id))
user = Repo.preload(asciicast, :user).user
png_params = Asciicast.png_params(asciicast, user)
case PngGenerator.generate(asciicast) do
case PngGenerator.generate(asciicast, png_params) do
{:ok, png_path} ->
conn
|> put_resp_header("content-type", MIME.path(png_path))

@ -1,5 +1,10 @@
defmodule Asciinema.Asciicast do
use Asciinema.Web, :model
alias Asciinema.{User, Asciicast}
alias Asciinema.PngGenerator.PngParams
@default_png_scale 2
@default_theme "asciinema"
schema "asciicasts" do
field :version, :integer
@ -10,6 +15,10 @@ defmodule Asciinema.Asciicast do
field :private, :boolean
field :secret_token, :string
field :duration, :float
field :theme_name, :string
field :snapshot_at, :float
belongs_to :user, User
end
def by_id_or_secret_token(thing) do
@ -31,4 +40,18 @@ defmodule Asciinema.Asciicast do
def json_store_path(%__MODULE__{id: id, stdout_frames: stdout_frames}) when is_binary(stdout_frames) do
"asciicast/stdout_frames/#{id}/#{stdout_frames}"
end
def snapshot_at(%Asciicast{snapshot_at: snapshot_at, duration: duration}) do
snapshot_at || duration / 2
end
def theme_name(%Asciicast{theme_name: a_theme_name}, %User{theme_name: u_theme_name}) do
a_theme_name || u_theme_name || @default_theme
end
def png_params(%Asciicast{} = asciicast, %User{} = user) do
%PngParams{snapshot_at: snapshot_at(asciicast),
theme: theme_name(asciicast, user),
scale: @default_png_scale}
end
end

Loading…
Cancel
Save