Maybe just use ipycanvas instead - it's on PyPI :) It works the same way except it's not a hack. I found it after I posted.
I went through:
- matplotlib animations (super slow, not live)
- writing an image with PIL and updating display (flickers)
- custom html+canvas code
- ipycanvas
I call display() on the canvas and then run the draw update loop on the canvas later in the same cell. That way the canvas is first displayed and then "live" updated.