Skip to content

Commit

Permalink
Configure busway signs for Rte 716 (#762)
Browse files Browse the repository at this point in the history
* feat: create-take script

* feat: add headsign, takes for Rte 716, Cobbs Corner Canton
  • Loading branch information
sloanelybutsurely authored Jun 21, 2024
1 parent e2bf835 commit 53ded35
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 4 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,7 @@ erl_crash.dump
*.ez

# local direnv configuration
/.envrc
/.envrc

/priv/tmp
/priv/output
9 changes: 6 additions & 3 deletions lib/pa_ess/utilities.ex
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,8 @@ defmodule PaEss.Utilities do
{"Waltham", ["Waltham"]},
{"Haymarket", ["Haymrkt", "Haymarkt", "Haymarket"]},
{"Silver Line Way", ["Slvr Ln Way"]},
{"Gallivan Blvd", ["Gallivn", "Gallivan"]}
{"Gallivan Blvd", ["Gallivn", "Gallivan"]},
{"Cobbs Corner Canton", ["Canton"]}
]

@spec headsign_abbreviations(String.t() | nil) :: [String.t()]
Expand Down Expand Up @@ -596,7 +597,8 @@ defmodule PaEss.Utilities do
{"Chelsea", "860"},
{"Gallivan Blvd", "881"},
{"Brookline Ave", "885"},
{"Brookline Village", "886"}
{"Brookline Village", "886"},
{"Cobbs Corner Canton", "887"}
]

@route_take_lookup %{
Expand Down Expand Up @@ -654,7 +656,8 @@ defmodule PaEss.Utilities do
"226" => "809",
"230" => "810",
"236" => "811",
"245" => "628"
"245" => "628",
"716" => "888"
}

@atom_take_lookup %{
Expand Down
118 changes: 118 additions & 0 deletions scripts/create-take.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
#!/usr/bin/env -S ERL_FLAGS=+B elixir
Logger.configure(level: :info)

Mix.install([{:phoenix_html, "~> 4.1"}])

defmodule CreateTake do
@moduledoc """
Creates a Text-to-Speech audio files using AWS Polly for TTS and Sox for
audio conversion and resampling.
NOTE: Requires the AWS CLI and Sox to be installed and configured.
Output WAV files are written to `priv/output`.
Polly generated MP3s are kept in `priv/tmp`. These files are only used to
prevent duplicate calls to the Polly API. You can safely delete these files.
## Usage
1. Generate an audio file:
$ ./scripts/create-take.exs --text "Hello, World!" --name hello-world
2. Force regeneration of audio using Polly:
$ ./scripts/create-take.exs --text "Hello, World!" --name hello-world --force
3. Output this message:
$ ./scripts/create-take.exs --help
"""
require Logger

@args [help: :boolean, text: :string, name: :string, force: :boolean]
def main(args) do
{parsed, []} = OptionParser.parse!(args, strict: @args)

parsed = Map.new(parsed)

cmd(parsed)
end

defp cmd(%{help: true}), do: usage()

@default_polly_args ~w[
--engine neural
--language-code en-US
--voice-id Matthew
--lexicon-names mbtalexicon
--text-type ssml
--output-format mp3
--sample-rate 22050
--region us-east-1
]

defp cmd(%{text: text, name: name} = opts) when is_binary(text) and is_binary(name) do
Logger.info("Converting text to speech...")

File.mkdir_p!("priv/tmp")
File.mkdir_p!("priv/output")

text_hash =
:crypto.hash(:sha256, text)
|> Base.encode16(case: :lower)

polly_output = Path.join(File.cwd!(), "priv/tmp/#{text_hash}.mp3")

force? = Map.get(opts, :force, false)

if File.exists?(polly_output) and not force? do
Logger.info("Polly generated file exists, reusing. Use '--force' to force regenration.")
else
Logger.info("Generating audio file using Polly.")

{_, 0} =
System.cmd(
"aws",
["polly", "synthesize-speech" | @default_polly_args] ++
["--text", to_ssml(text), polly_output]
)
end

Logger.info("Converting Polly MP3 file to 8-bit WAV")

wav_output =
Path.join([
File.cwd!(),
"priv/output",
name
])

wav_output = if Path.extname(wav_output) == ".wav", do: wav_output, else: wav_output <> ".wav"

{_, 0} = System.cmd("sox", [polly_output, "-r", "11025", "-b", "8", wav_output])

Logger.info("8-bit WAV file: #{wav_output}")

Logger.info("Done.")
end

defp cmd(args) do
Logger.error("Unrecognized options: #{inspect(args)}")

usage()
end

defp usage, do: IO.puts(@moduledoc)

defp to_ssml(text) do
{:safe, text} = Phoenix.HTML.html_escape(text)

~s|<speak><amazon:effect name="drc"><prosody volume="x-loud">#{text}</prosody></amazon:effect></speak>|
end
end

System.argv()
|> CreateTake.main()

0 comments on commit 53ded35

Please sign in to comment.