I thought maybe I saw a call for more info somewhere I thought to add this.
Even though Resume helps and explains lots I would still say it's broken and not great in design vs dev-user experience expectations.
I was trying to hack around this cancel problem and saw 'speaking' stuck (says true but not paused and nothing speaking) and took utterances onend methods and tried to set speaking to false there etc. Nothing worked (override the speaking setter getter etc.).
If it was me I would make the SpeechSynthesis have an accessible and editable cue (queue) (shift, swap, etc.).
Utterance re-usability likely is still broken. You should be able to create an utterance on say a rollover event and reuse it as the user mouses over the same item, saves resources volume etc.
So you could also imagine some of the utterances are not 'cancellable' (= false, default is true), but still be able to override that cancelAll etc. [cancel( item );]
You'll need to open the console log and remember to click in the HTML white box first before 'run' to activate speaking (now blocked until first click).
Ultimately the values for speaking and paused are like this:
speak A - ss.speaking:false
speak A - ss.paused:false
cancel - ss.speaking:false
cancel - ss.paused:false
speak B - ss.speaking:false
speak B - ss.paused:false
resume - ss.speaking:false
resume - ss.paused:false
I think the issue might be they all need to be async or something? It was extremely confusing to determine what was going on when.