erdnaxeli / castblock

Automatically skip sponsor segments and ads in YouTube videos playing on Chromecast.
MIT License
182 stars 20 forks source link

Feature: Mute native youtube ads #17

Closed stephen304 closed 3 years ago

stephen304 commented 3 years ago

This is a proof of concept for automatically muting / unmuting native youtube ads shown on chromecast. It uses the (seemingly) magic number 1081 which playerState is set to while ads are running, and I added a set_mute function which uses the http api of go-chromecast. I also added a --mute-ads flag to enable this behavior.

I'm not particularly attached to this implementation since I had to change some stuff in the WatchMessage struct due to not being familiar with crystal. Let me know what you think - it seems to work pretty well so far. Repeated calls to mute/unmute are not handled but it doesn't seem to harm anything. There are other improvements that could be made like cleaner parsing of the payload json.

Edit: Also there might still be a bug with the payload json traversal, I tried to prevent cases that would cause a fatal error but it happens occasionally

stephen304 commented 3 years ago

For reference, here is the relevant message from go-chromecast

{
  "destination_id": "*",
  "namespace": "urn:x-cast:com.google.cast.media",
  "payload": "{\"type\":\"MEDIA_STATUS\",\"status\":[{\"mediaSessionId\":1791717783,\"playbackRate\":1,\"supportedMediaCommands\":262273,\"volume\":{\"level\":1,\"muted\":false},\"playerState\":\"BUFFERING\",\"customData\":{\"playerState\":1081},\"media\":{\"contentId\":\"DO0cyBzk4NI\",\"contentType\":\"x-youtube/video\",\"customData\":{\"listId\":\"RQlR57D8ejiW0B66ohS2sXV91W9aQ\",\"currentIndex\":7},\"streamType\":\"BUFFERED\",\"metadata\":{\"metadataType\":0,\"title\":\"Paint Tips and Tricks For The Best Results Possible | Outdoor Kitchen Part 8\",\"subtitle\":\"April Wilkerson\",\"images\":[{\"url\":\"https://i.ytimg.com/vi/DO0cyBzk4NI/hqdefault.jpg\"}]}}}]}",
  "proto_version": 0,
  "source_id": "d27a7c05-3190-40a0-8ac6-1433bdf669bd",
  "type": "MEDIA_STATUS"
}
stephen304 commented 3 years ago

@erdnaxeli I managed to figure out the struct stuff so hopefully it looks better now. I also have it check the mute status before it tries to mute. It still tries to mute/unmute 2 times, it seems because several events happen quickly before the command goes through, but it doesn't seem to have any negative effect.

Edit: 1 remaining bug as far as I can tell is that if you skip to a different video while an ad is playing, it doesn't unmute.

Edit: Also it appears there is still some out of bounds condition - maybe you have some ideas

stephen304 commented 3 years ago

Thanks, that should hopefully fix whatever crash I had before. Do you have any thoughts on how to handle a missing ad end message to trigger unmute like when changing videos while an ad is playing? The current worst case scenario is having to unmute using the phone volume buttons if this happens, I'm not sure if you want to handle that scenario.

erdnaxeli commented 3 years ago

Do you have any thoughts on how to handle a missing ad end message to trigger unmute like when changing videos while an ad is playing? The current worst case scenario is having to unmute using the phone volume buttons if this happens, I'm not sure if you want to handle that scenario.

I am not sure how to handle that. We could store a state that says "the sound is muted, and that's because of us", so when we see a video playing and the sound still muted and it's because of us we could unmute it. But for now as this is a behavior disabled by default I am ok to merge this PR as it is now.

erdnaxeli commented 3 years ago

Btw could you update the README? You can add the new option and add yourself to the contributors list if you want :)

I think you will need to rebase the branch on master, as I edited the README since this PR is open.

stephen304 commented 3 years ago

That should cover it