         speed (:speed player)
         all-frames (-> player :source :frames)
         frames (-> all-frames (next-frames start-at) (frames-at-speed speed))
-        frames-ch (coll->chan frames)
+        stop-playback-ch (chan)
+        frames-ch (pipe (coll->chan frames) stop-playback-ch)
         events-ch (screen-events frames-ch)
         elapsed-time #(* (elapsed-time-since start) speed)
-        timer-ch (coll->chan (repeatedly (fn []
-                                           [0.3 (+ start-at (elapsed-time))])))
-        stop-playback-ch (chan)
+        time-events (repeatedly (fn [] [0.3 (+ start-at (elapsed-time))]))
+        timer-ch (pipe (coll->chan time-events) stop-playback-ch)
         stop-fn (fn []
                   (close! stop-playback-ch)
                   (elapsed-time))]

  [frames-ch]
  (priority-chan [:frame frames-ch] [:blink make-cursor-blink-chan]))

(defmulti start-playback
  "The heart of the player. Coordinates dispatching of state update events like
  terminal line updating, time reporting and cursor blinking. Returns player

  for each element. It tries to always stay 'on the schedule' by measuring
  elapsed time and skipping elements if necessary."
  [coll]
  (let [ch (chan)
        start (js/Date.)]
    (go
      (loop [coll coll
