The answer depends on what's actually going on. I've yet to do this sort of thing in Rust but, when I was doing it in Python and initializing curses for a TUI (i.e. like a GUI but made using text), I remember the curses wrapper's initialization stuff handling that for me.
Because of the way terminal emulation works, there are actually two buffers: the one inside the fake terminal hardware that lets the user accumulate and backspace characters before sending the data over the fake wire when you press Enter and the one on the receiving end of the wire.
Paste your initialization code for your curses wrapper and I'll take a look at it after I've had breakfast.
The problem with making a custom web server is that you take responsibility for re-solving all the non-obvious security vulnerabilities. I always try to delegate as much network-facing code as possible to a mature implementation someone else wrote for that reason.
Here's how I'd implement it, based on stuff I've done before:
std::thread
to bring up mpv in a separate thread.tokio::sync::oneshot
in the "job order" object your async code drops into the channel and then have the async taskawait
the receiving side. That way, you can have the async task block on the some kind of completion signal from the sync thread without blocking the thread(s) underlying the task executor.