github robert-dean/deadair v0.14.0
deadair 0.14.0

latest releases: v0.90.4, v0.90.3, v0.90.2...
one month ago
  • A phone-in joined into one piece of audio now takes up its real length in the running order. It always went in as one item and the item never said how long it ran, so the clock treated a ten-minute programme as taking no time at all and planted whatever came next on top of it: the news at the top of the hour arriving ten minutes into a call. An episode of somebody else's podcast has been placed with its length for a while; a programme the station made itself now is too, measured by the mixer that joined it rather than claimed by a publisher.
  • Plugins can now offer text for the station to read out. A narration plugin says what series it has (a book, a newsletter, a queue of long reads), what instalments each one holds, and the words of one when the station asks for them. The station speaks it itself, in its presenter's voice, so a chapter gets the pronunciation lexicon and the performance cues the station's own words get. Nothing carries it on air yet; that follows.
  • Put a narration band on the format clock and the station reads at that time: the next chapter of a book, or the newest issue of a column, in the presenter's voice, with a talk break in front of it introducing what is coming. The mount names the piece and the series while it plays, and the station remembers where it got to, so tomorrow's band reads the next chapter rather than the same one. A band with nothing left to read goes quiet and says why rather than airing something else.
  • The station can now read a piece out loud. Ahead of a narration band's slot it fetches the words, splits them into as few parts as its speech engine will take, and speaks each one in the presenter's voice, with the pronunciation lexicon and everything else the station's own words get, then has the mixer join them into one recording. It works well ahead of time and yields to anything the presenter needs now, so a chapter being made never delays a break. Nothing airs it yet; the band that places it follows.
  • A Readings page in the Library, beside Podcasts: what the station has been given to read, every piece of it, and where the station has got to. Each one says whether it has been spoken yet, is being spoken now, or could not be and why, and any of them can be read out of turn. A narration band's topic can pick a series from the same list rather than needing an id typed in.
  • The station now keeps track of what it has been given to read out. A narration plugin says what series it offers (a book, a column, a queue of long reads), and the station remembers every piece of each, in the order that series is worked through: a book from its first chapter, a column from its newest issue. It re-reads the list twice an hour, and the Clock can point a narration band at one of them. Nothing is spoken or aired yet; that follows.
  • A speech plugin can now say how much text its engine takes in one go, and the station knows how to cut something longer than that into as few calls as will fit. It cuts at the strongest boundary available, between paragraphs first, then between sentences, then between words, because a cut mid-sentence is audible where a slightly longer call is not. Nothing a presenter says is anywhere near any engine's limit, so no break changes; this is groundwork for reading something long out loud.
  • A phone-in being made for later no longer holds the speech engine in front of the breaks the presenter needs now. Its beats were queued at the same rank as anything on air, so a break planted while a programme was being spoken waited behind every remaining beat of it. A programme now yields to the station while its slot is far off and takes precedence as that slot approaches, which is the same earliest-deadline rule its writing already followed.
  • A mistyped DATABASE_PORT now stops the station with a message naming it. It was read as config.get('DATABASE_PORT', 55432), which types as number and answers the string '5432' whenever the variable is actually set, and worked only because pg coerces it on the way into the socket. A value the parser could not read took the same path and became NaN, which is falsy, so pg read it as a port nobody set and fell through to PGPORT and then to its own 5432: DATABASE_PORT=54 32 surfaced as a refused connection, or as authentication against whatever else answers on 5432, rather than as the two characters that caused it. It goes through requiredNumber now, like REDIS_PORT beside it, which refuses a value that is present and unreadable and falls back only for a key nobody set. Its tests passed the port as a real number for as long as they existed, which proved nothing about a resolver whose whole bug was the string, so they pass strings now and the fixture type refuses anything else.
  • The station can be pointed at a Redis that asks for a password. It read REDIS_HOST and REDIS_PORT and nothing else, so an operator whose cache wants AUTH had no way to say so and #160 ran a second Redis daemon beside the one they already had. REDIS_USERNAME, REDIS_PASSWORD and REDIS_TLS now sit beside the address (a Redis with only requirepass set takes the password alone and no username; REDIS_TLS is the connection rather than the password, and without it the password travels in the clear), and REDIS_URL takes the whole thing as one string instead, which is the shape a hosted Redis hands you and the only way to name a database index. Set the URL and it is the entire answer: the five discrete variables are not consulted at all, because a merge of the two is a station connecting to the right host as the wrong user, and the full image fills the loopback ones in itself. A URL it cannot read stops the boot rather than falling back to localhost, and no message about it ever quotes the value, since a Redis URL carries the password. REDIS_PASSWORD and REDIS_URL are scrubbed from process.env after the config snapshot resolves, like the database password already was. Everything that talks to Redis (both rate limiters, the sign-in mail limiter, the cache and the session store) shares the one client, so all of it is covered. REDIS_PORT is read through requiredNumber in the same pass: it was handing ioredis the string '6379' whenever it was set and working only because the connector coerces it, so REDIS_PORT=63 79 was a NaN port rather than an error naming the variable.

Don't miss a new deadair release

NewReleases is sending notifications on new releases.