1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
{ depot, pkgs, lib, ... }:

let
  unwrapped = depot.nix.buildGo.program {
    name = "observations";
    srcs = [
      ./main.go
      ./episode.go
      ./listen.go
      ./probe.go
      ./render.go
      ./transcript.go
      ./transcriptfile.go
      ./transcripthtml.go
    ];
  };

in
pkgs.symlinkJoin {
  name = "observations";
  outputs = [ "out" "man" ];
  paths = [ unwrapped ];
  buildInputs = [ pkgs.makeWrapper ];

  postBuild = ''
    # ffprobe reads the duration and byte size that the feed's <enclosure>
    # needs, and ffmpeg copies the transcript track out of the container.
    # Neither is optional: `add` refuses to ingest without them. Putting
    # ffmpeg in the closure means the tool works wherever it is installed
    # rather than only where ffmpeg happens to be on PATH.
    wrapProgram $out/bin/observations \
      --prefix PATH : ${lib.makeBinPath [ pkgs.ffmpeg-headless ]}

    mkdir -p $man/share/man/man1 $man/share/man/man5 $man/share/man/man7
    cp ${./observations.1} $man/share/man/man1/observations.1
    cp ${./observations-transcripts.5} \
      $man/share/man/man5/observations-transcripts.5
    cp ${./observations.7} $man/share/man/man7/observations.7
    cp ${./observations-transcripts.7} \
      $man/share/man/man7/observations-transcripts.7
  '';

  meta = {
    description = "Publish audio readings of other people's texts";
    longDescription = ''
      observations is an audio format: one person reading a short text out
      loud — an essay, a blog post — and thinking about it while doing so.
      This tool ingests such a recording and renders a static site and a
      podcast feed from it.

      The recording is served exactly as it came off the recorder, because
      Google Recorder embeds a word-level transcript inside the .m4a that any
      transcode would silently destroy. `add` extracts that transcript at
      ingest time and refuses recordings that no longer carry one.

      See observations(7) for the reasoning and observations(1) for the
      reference.
    '';
  };
}