-
-
Save pcworld/3198763 to your computer and use it in GitHub Desktop.
#!/bin/bash | |
#Linux Spotify Ad Mute v1 - simply run this script after you've started Spotify. | |
#System sound will be muted as soon as an ad plays | |
#Find updated versions at: http://pcworldsoftware.kilu.net/files/link_spotify-admute.php and/or https://gist.github.com/pcworld | |
# | |
#Copyright (c) 2012, "pcworld", 0188801@gmail.com | |
#All rights reserved. | |
# | |
#Redistribution and use in source and binary forms, with or without | |
#modification, are permitted provided that the following conditions are met: | |
# * Redistributions of source code must retain the above copyright | |
# notice, this list of conditions and the following disclaimer. | |
# * Redistributions in binary form must reproduce the above copyright | |
# notice, this list of conditions and the following disclaimer in the | |
# documentation and/or other materials provided with the distribution. | |
# * Neither the name of the author nor the | |
# names of its contributors may be used to endorse or promote products | |
# derived from this software without specific prior written permission. | |
# | |
#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |
#ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
#WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
#DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY | |
#DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
#(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
#LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
#ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
#(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
#SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
dbus-monitor "type='signal',path='/org/mpris/MediaPlayer2',member='PropertiesChanged'" | grep --line-buffered 'string "Metadata"' | | |
while read -r line ; do | |
if ! [[ "`dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify / org.freedesktop.MediaPlayer2.GetMetadata`" == *'string "mpris:artUrl"'* ]] | |
then | |
pactl set-sink-mute 0 yes | |
else | |
pactl set-sink-mute 0 no | |
fi | |
done |
hi i'm trying to let the script play a radiostream via vlc.
it starts the stream and mutes spotify whenever an add-break appears but i always have to kill the vlc process by killing the running spotify-admute-script and then restart the script.
If i start the radiostream (cvlc URL) in a terminal i can easily kill it with pkill vlc whenever i want.
hopefully you can help me to get this running.
here's the hint i used: https://gist.github.com/pcworld/3198763/#comment-584571
and here's my mute-script:
#!/bin/bash
was_paused=0 # if last state was paused
ad=0 # if an ad is probably playing right now
while true; do
num=$(LC_ALL=C pactl list | grep -E '(^Sink Input)|(media.name = \"Spotify\"$)' | awk '/Spotify/ {print a} {a = $0}' | cut -c 13-)
icon_name=$(xprop -name 'Spotify - Linux Preview' _NET_WM_ICON_NAME | cut -d \" -f 2)
song_name=$(dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify / org.freedesktop.MediaPlayer2.GetMetadata | grep xesam:title -A 1 | grep variant | cut -d \" -f 2)
if [[ "$song_name" && "$icon_name" =~ "$song_name" ]]; then
if [ "$was_paused" -eq 0 -a "$ad" -ne 0 ]; then
# wait 1 second after a commercial
sleep 1
pkill vlc
fi
ad=0
pkill vlc
pactl set-sink-input-mute $num no
else
ad=1
pactl set-sink-input-mute $num yes
cvlc ~/Downloads/BassDrive.pls
fi
if [ "$icon_name" = "Spotify" ]; then
was_paused=1
pkill vlc
else
was_paused=0
fi
sleep 0.5
done
thx :)
okay, cause i'm quite new to linux, bash, ... etc. i didn't really thought about what i'm doing with the script. since i figured out whats happening there i added the variable vlc_running and changed the first if-fi-block to:
if [[ "$song_name" && "$icon_name" =~ "$song_name" ]]; then
if [ "$was_paused" -eq 0 -a "$ad" -ne 0 ]; then
# wait 1 second after a commercial
sleep 1
fi
#checks if vlc is still running then kills it
if [ "$vlc_running" -eq 1 ]; then
pkill vlc
vlc_running=0
fi
ad=0
pactl set-sink-input-mute $num no
else
ad=1
pactl set-sink-input-mute $num yes
if [ "$vlc_running" -eq 0 ]; then
cvlc ~/Downloads/BassDrive.pls &
vlc_running=1
fi
fi
now everything's working as expected...
but is there any better way to do this? i mean is it bad what i did there (from a programmers perspective)?
anything you would do different? i'm just trying to get some input :)
I used this script and the custom while loop in the first comment, and now Spotify will not unmute. Any song I play, there is no sound coming from Spotify. I tried uninstalling and reinstalling Spotify and re-running the script, but no success. Help please!
epleaner:
Your spotify is muted in the pulseaudio volume control. Open pulseaudio volume control, select playback tab, and click the speaker icon near spotify. It will unmute it.
Here's a rewrite of my script. It now relies on DBus information rather than the icon name. (It uses icon name to only monitor when spotify is paused or when spotify changes)
Script automatically kicks spotify up and waits until its ready.
Script includes the support for icecast audio streamer and a trick to keep spotify playing if it pauses for too long.
#!/bin/bash
## Config ##
IceUser="IceCast Username"
IcePass="IceCast password"
IceMount="%2Fmystream.mp3"
#^- Location of the icecast stream - %2F = /
BaseURL="http://localhost:8000/admin/metadata?mount=$IceMount&mode=updinfo&song="
#^- Where icecast itself is - localhost port 8000 is the default
##/Config ##
## Spotify Launch ##
spotify &>/dev/null &
spotiPid=$!
wait=1
printf "Spotify pid is $spotiPid\n"
while [ $wait = 1 ]; do
printf "Waiting for spotify...\n"
sleep 5
icon=$(xprop -name 'Spotify - Linux Preview' WM_ICON_NAME &>/dev/null)
if [ $? == 0 ]; then
wait=0
fi
done
##/Spotify Launch ##
WAKEUPS=0
POKECOUNT=0
PREVTITLE=""
COUNT=0
while [ 1 ] ; do
if [[ ! -d "/proc/$spotiPid" ]]; then
printf "Spotify exited. Quitting.\n"
break
fi
TITLE=`xprop -name 'Spotify - Linux Preview' WM_ICON_NAME | awk -F\" '{ print $2; }'`
NEW=0
AD=0
PAUSE=0
if [ "$TITLE" != "$PREVTITLE" ]; then
META=$(dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify / org.freedesktop.MediaPlayer2.GetMetadata)
song_name=$(echo -n "$META" | grep xesam:title -A 1 | grep variant | cut -d \" -f 2)
song_album=$(echo -n "$META" | grep xesam:album -A 1 | grep variant | cut -d \" -f 2)
song_artist=$(echo -n "$META" | grep xesam:artist -A 2 | grep string | grep -v xesam | cut -d \" -f 2)
song_track=$(echo -n "$META" | grep xesam:trackNumber -A 1 | grep variant | awk '{ printf $3; }')
song_cd=$(echo -n "$META" | grep xesam:discNumber -A 1 | grep variant | awk '{ printf $3; }')
song_rating=$(echo "$META" | grep xesam:autoRating -A 1 | grep variant | awk '{ printf $3; }')
PREVTITLE="$TITLE"
printf "\n\nWakeups=$WAKEUPS, Rating=$song_rating\n"
POKECOUNT=0
NEW=1
fi
if [ "$song_rating" == "" ]; then
printf " "
POKECOUNT=$(($POKECOUNT + 1))
AD=1
fi
if [ "$TITLE" == "Spotify" ]; then
printf " "
POKECOUNT=$(($POKECOUNT + 1))
AD=1
PAUSE=1
fi
if [ $POKECOUNT -gt 600 ]; then
WAKEUPS=$(($WAKEUPS + 1))
#dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.PlayPause >/dev/null
#^- Uncomment if you want to keep spotify constantly playing.
POKECOUNT=0
fi
if [ "$NEW" == "1" ]; then
## Pulseaudio wait ##
if [ "$PAUSE" == "0" ]; then
waitPulse=1
while [ $waitPulse -eq 1 ]; do
num=$(pactl list | grep -E '(^Sink Input)|(media.name = \"Spotify\"$)' | awk '/Spotify/ {print a} {a = $0}' | cut -c 13-)
if [[ ! -z "$num" ]]; then
waitPulse=0
else
sleep 0.1
fi
done
fi
##/Pulseaudio wait ##
if [ "$AD" == "1" ]; then
pactl set-sink-input-mute $num yes
song_artist="Spotify"
song_name="Advert"
song_album=""
else
pactl set-sink-input-mute $num no
fi
## IceCast update ##
if [ ! -z "$song_rating" ]; then
if [ $song_cd -gt 0 ]; then
Track=$((($song_cd * 100) + $song_track))
else
Track=$(($song_track + 100))
fi
Title="$song_artist [$song_album] $Track - $song_name"
fi
if [ -z "$song_album" ]; then
Title="$song_artist - $song_name"
fi
Song=$(echo -n "$Title" | perl -e "\$in=<STDIN>; utf8::decode(\$in); printf(\$in);" | perl -pe's/([^-_.~A-Za-z0-9])/sprintf("%%%02X", ord($1))/seg');
printf "$Title ."
#wget -O /dev/null --tries=1 --user=$IceUser --password=$IcePass --auth-no-challenge -q $BaseURL$Song
#^- IceCast update. Remove comment only if you have a working icecast server
fi
## Animation ##
COUNT=$(($COUNT + 1))
if [ "$COUNT" == "1" ]; then printf "\b-"; fi
if [ "$COUNT" == "2" ]; then printf "\b\\"; fi
if [ "$COUNT" == "3" ]; then printf "\b|"; fi
if [ "$COUNT" == "4" ]; then printf "\b/"; fi
if [ "$COUNT" == "5" ]; then COUNT=1; printf "\b-"; fi
##/Animation ##
unset META
sleep 0.2
done
test -z "`jobs -p`" || kill `jobs -p`
exit 0
How to use this script?
@Augustris, this depends on the OS you are using. In my case it is openSUSE - and I just placed the script into /home/$USER/bin/ and modified the launcher on my desktop to start mentioned script instead of the usual Spotify binary. Works great, no ads any more! 😄 @AmpGod, is there a way to update the script to cut out the muted time of the ad in order to just play the next song? That would be the ultimate and perfect solution to all nagging!
@SecUpwN :
Here are two solutions that might be what you are looking for. They are based on the fantastic work by @pcworld, @OlegSmelov, @AmpGod and all the others in this thread.
Script 1: spotify-automute-simple
This script will automatically mute Spotify when an ad comes on and loop an audio file until it's over. Make sure to change PLAYER and LOOPTRACK for your system.
#!/bin/bash
# spotify-automute-simple
# - automatically mute Spotify when ad comes on and loop short track
# - automatically switch back to Spotify when ad over
# Settings
PLAYER="mpv --loop=inf"
LOOPTRACK="$HOME/Music/Alerts/Jeopardy_loop.mp3"
# VAR
WMTITLE="Spotify - Linux Preview"
ADMUTE=0
PAUSED=0
# FCT
get_pactl_nr(){
pactl list | grep -E '(^Sink Input)|(media.name = \"Spotify\"$)' | cut -d \# -f2 \
| grep -v Spotify
}
# MAIN
xprop -spy -name "$WMTITLE" WM_ICON_NAME |
while read -r XPROPOUTPUT; do
XPROP_TRACKDATA="$(echo "$XPROPOUTPUT" | cut -d \" -f 2 )"
DBUS_TRACKDATA="$(dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify / \
org.freedesktop.MediaPlayer2.GetMetadata | grep xesam:title -A 1 | grep variant | cut -d \" -f 2)"
echo "XPROP: $XPROP_TRACKDATA"
echo "DBUS: $DBUS_TRACKDATA"
if [[ "$XPROP_TRACKDATA" = "Spotify" ]]
then
echo "--PAUSED--"
PAUSED="1"
else
PAUSED=0
echo "--NOTPAUSED--"
fi
if [[ "$PAUSED" = "1" || "$XPROP_TRACKDATA" =~ "$DBUS_TRACKDATA" ]]
then
echo "--NOAD--"
if [[ "$ADMUTE" = "1" ]]
then
sleep 0.5
kill -s TERM "$ALTPID"
for PACTLNR in $(get_pactl_nr); do
pactl set-sink-input-mute "$PACTLNR" no > /dev/null 2>&1
echo "Unmuting sink $PACTLNR"
done
fi
ADMUTE=0
else
echo "--AD--"
if [[ "$ADMUTE" != "1" ]]
then
for PACTLNR in $(get_pactl_nr); do
pactl set-sink-input-mute "$PACTLNR" yes > /dev/null 2>&1
echo "Muting sink $PACTLNR"
done
$PLAYER "$LOOPTRACK" > /dev/null 2>&1 &
ALTPID="$!"
fi
ADMUTE=1
fi
done
echo "Spotify not active. Exiting."
exit 0
Script 2: spotify-automute-continuous
This script deals with ads slightly differently. It will automatically mute Spotify and play a random MP3 found in LOCALMUSIC. Instead of unmuting Spotify as soon as the ad is over this script will wait until the local MP3 is played fully before switching Spotify back on. This way you can have a continuous stream of music with no interruption whatsoever.
#!/bin/bash
# spotify-automute-continuous
# - automatically mute Spotify when ad comes on and play random local file
# - automatically continue Spotify playback afterwards
# Settings
LOCALMUSIC="$HOME/Music"
ALERT="/usr/share/sounds/gnome/default/alerts/glass.ogg"
PLAYER="mpv --vo null"
# VAR
WMTITLE="Spotify - Linux Preview"
ADMUTE=0
PAUSED=0
# FCT
print_horiz_line(){
printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' -
}
spotify_playpause(){
dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 \
org.mpris.MediaPlayer2.Player.PlayPause > /dev/null 2>&1
}
get_pactl_nr(){
pactl list | grep -E '(^Sink Input)|(media.name = \"Spotify\"$)' | cut -d \# -f2 \
| grep -v Spotify
}
player(){
RANDOMTRACK="$(find "$LOCALMUSIC" -name "*.mp3" | sort --random-sort | head -1)"
notify-send -i spotify "Spotify ad muter" "Playing ${RANDOMTRACK##*/}"
$PLAYER "$ALERT"
$PLAYER "$RANDOMTRACK"
spotify_playpause # continue Spotify playback. This triggers the xprop spy and
# subesequent actions like unmuting Spotify
}
# MAIN
xprop -spy -name "$WMTITLE" WM_ICON_NAME |
while read -r XPROPOUTPUT; do
XPROP_TRACKDATA="$(echo "$XPROPOUTPUT" | cut -d \" -f 2 )"
DBUS_TRACKDATA="$(dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify / \
org.freedesktop.MediaPlayer2.GetMetadata | grep xesam:title -A 1 | grep variant | cut -d \" -f 2)"
echo "XPROP: $XPROP_TRACKDATA"
echo "DBUS: $DBUS_TRACKDATA"
if [[ "$XPROP_TRACKDATA" = "Spotify" ]]
then
echo "PAUSED: Yes"
PAUSED="1"
else
PAUSED="0"
echo "PAUSED: No"
fi
if [[ "$PAUSED" = "1" || "$XPROP_TRACKDATA" =~ "$DBUS_TRACKDATA" ]]
then
echo "AD: No"
if [[ "$ADMUTE" = "1" ]]
then
if ps -p $ALTPID > /dev/null 2>&1 # if alternative player still running
then
if [[ "$PAUSED" != "1" ]] ## and if track not yet paused
then
spotify_playpause ### then pause
echo "##Pausing Spotify until local playback finished##"
fi
continue ## reset loop
else # if player not running
for PACTLNR in $(get_pactl_nr); do
pactl set-sink-input-mute "$PACTLNR" no > /dev/null 2>&1 ## unmute
echo "##Unmuting sink $PACTLNR##"
echo "##Switching back to Spotify##"
done
fi
fi
ADMUTE=0
else
echo "AD: Yes"
if [[ "$ADMUTE" != "1" ]]
then
for PACTLNR in $(get_pactl_nr); do
pactl set-sink-input-mute "$PACTLNR" yes > /dev/null 2>&1
echo "##Muting sink $PACTLNR##"
done
if ! ps -p $ALTPID > /dev/null 2>&1
then
echo "##Switching to local playback##"
player > /dev/null 2>&1 &
ALTPID="$!"
fi
fi
ADMUTE=1
fi
printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' -
done
echo "Spotify not active. Exiting."
exit 0
Installation of the scripts
I would recommend moving one (or both) of these script to your PATH (e.g. $HOME/bin on Ubuntu) and then writing a wrapper script to start them automatically when Spotify gets started. You don't have to worry about terminating them when Spotify exits because that happens automatically.
Here is the wrapper script I am using:
#!/bin/bash
spotify "$@" > /dev/null 2>&1 &
sleep 20
if [[ -z "$(pgrep spotify-aut)" ]]
then
spotify-automute > /dev/null 2>&1 &
fi
Some notes:
- We use sleep to give Spotify enough time to start up (otherwise the script will exit)
- Before starting the script we first check if it's running already.
- The redirection of stdout and stderr to /dev/null and the ampersand make sure that the processes can safely be moved to the background. This way the wrapper can exit after launching Spotify and the script.
Make sure to replace the script name in the wrapper with its name on your system!
One last reminder
Spotify is a fantastic service and worth every penny. I am a premium subscriber myself but I wrote these scripts for my parents who are still a bit reluctant and hesitant with these things.
Please do consider switching to premium, especially if you are planning to use Spotify on the go.
Anyway, I hope you found this useful.
@Feltzer, thank you for your updated version of the script. I especially like the one where local music is being played instead of an Ad. Unfrtunately, it doesn't work yet. Maybe because I have no Music in my local directory? Do I have to use the wrapper script or is it OK if I just modify the Spotify-Launcher to launch the full script (my current setup)? It would be awesome if you could update it once more the following way:
- Script works without having Music in the local directory (in this case just muting the Ad)
- Script shall be generic to work with updated clients (I'm always on the latest available client)
Is this possible for you? Thanks ahead! And just for anyone reading my post and being interested in security for your Android device: Have a look at the Android IMSI-Catcher Detector. You can thank me later. 😸
:(
it didn't worked for me neither.
I tryed with the two scripts. I made sure that the mp3 file/folder is there.
No idea what could be. :/
@Feltzer: Thanks for the nice script! I experienced the problem that no muting/unmuting was performed (I did not see "Unmuting sink ..." or "Muting sink ..." in the output), although the ad detection worked fine.
It turned out that this was a locale issue:
pactl list | grep -E '(^Sink Input)|(media.name = \"Spotify\"$)' | cut -d \# -f2 \
uses a locale-dependent regular expression. So, to everyone having the same problem: As other users have pointed out before me, a better way would be to replace the line by a language-independent version:
LC_ALL=C pactl list | grep -E '(^Sink Input)|(media.name = \"Spotify\"$)' | cut -d \# -f2 \
I feel like this script deserves its own Repository, so that more people can develop on it.
Welcome to the all-new and fresh Spotify-AdKiller-Project! 😈 LET'S PIMP IT UP!
Proper credit will be given - please tell me ASAP if you have any problem with anything.
@hairyheron Thanks for the fix!
@SecUpwN I think it's a great idea. Feel free to go ahead :)
@rhoconlinux As far as the playback issue is concerned, please check out my comment on the new issue tracker.
@SecUpwN i try it, and work perfectly.
thx very much for a comprehensible installation.
I executed this script with the while loop of the first comment and now no sound is coming when I play music! How can I revert what I just did?
Those scripts did not work for me anymore (I use ubuntu 14.04 and spotify 0.9.11.26) with the newest spotify version. So I went and modified them.
You have to start my script parallel to spotify and it will mute every commercial:
#!/bin/bash
# set commercial mute, so we do not neet to listen to them
echo "----------------------------------------------------------"
echo ""
echo " Mute spotify commercial"
echo ""
echo "----------------------------------------------------------"
WMTITLE="Spotify - Linux Preview"
xprop -spy -name "$WMTITLE" WM_ICON_NAME |
while read -r XPROPOUTPUT; do
XPROP_TRACKDATA="$(echo "$XPROPOUTPUT" | cut -d \" -f 2 )"
DBUS_TRACKDATA="$(dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify / \
org.freedesktop.MediaPlayer2.GetMetadata | grep xesam:title -A 1 | grep variant | cut -d \" -f 2)"
# show something
echo "XPROP: $XPROP_TRACKDATA"
echo "DBUS: $DBUS_TRACKDATA"
# first song should not be commerical
if [ "$OLD_XPROP" != "" ]
then
# check if old DBUS is the same as the new, if true then we have a commercial, so mute
if [ "$OLD_DBUS" = "$DBUS_TRACKDATA" ]
then
echo "commercial: yes"
amixer -D pulse set Master mute >> /dev/null
else
echo "commercial: no"
amixer -D pulse set Master unmute >> /dev/null
fi
else
echo "commercial: we don't know yet"
fi
echo "----------------------------------------------------------"
OLD_XPROP=$XPROP_TRACKDATA
OLD_DBUS=$DBUS_TRACKDATA
done
exit 0
It is based on the script of Feltzer
@openpaul your script assumes a commercial is playing when pausing and unpausing. I changed your second if statement to get around this.
if [ "$OLD_DBUS" = "$DBUS_TRACKDATA" ] && [ "$OLD_XPROP" != "Spotify" ]
@debrandt it is useful not to mute master volume, when you pause spotify.
i extended the if statement to the following
if [ "$OLD_DBUS" = "$DBUS_TRACKDATA" ] && [ "$OLD_XPROP" != "Spotify" ] && [ "$XPROP_TRACKDATA" != "Spotify" ]
❗ TO EVERYONE: This script has MATURED and MOVED into Spotify-AdKiller!
@SecUpwN i try it, and work perfectly.
thx very much for a comprehensible installation.
Thank you very much for your kind words. Unfortunately mentions are not possible within Gist, so I bet you'll never know how thankful I'm for this. Please join the development in my repository mentioned above. Cheers!
God job.
thanks to @felzer and others who have contributed.
I edited the version 1 to work with nuvolaplayer's spotify app on ubuntu 18.04. enjoy!
be sure to change the Player and Looptrack!
`
flatpak run eu.tiliado.NuvolaAppSpotify
#!/bin/bash
# spotify-automute-simple
# - automatically mute Spotify when ad comes on and loop short track
# - automatically switch back to Spotify when ad over
# Settings
#PLAYER="mpv --loop=inf"
#PLAYER = "mpv --no-audio"
PLAYER="mpv"
LOOPTRACK=""
# VAR
WM_NAME="Spotify"
ADMUTE=0
PAUSED=0
# FCT
get_pactl_nr(){
pactl list | grep -E '(^Sink Input)|(media.name = \"Spotify\"$)' | cut -d \# -f2 \
| grep -v Spotify
}
# MAIN
xprop -spy -name "$WM_NAME" WM_ICON_NAME |
while read -r XPROPOUTPUT; do
XPROP_TRACKDATA="$(echo "$XPROPOUTPUT" | cut -d \" -f 2 )"
DBUS_TRACKDATA="$(dbus-send --print-reply --dest=org.mpris.MediaPlayer2.NuvolaAppSpotify /org/mpris/MediaPlayer2 \
org.freedesktop.DBus.Properties.Get string:'org.mpris.MediaPlayer2.Player' string:'Metadata' | grep xesam:title -A 1 | grep variant | cut -d \" -f 2)"
echo "XPROP: $XPROP_TRACKDATA"
echo "DBUS: $DBUS_TRACKDATA"
if [[ "$DBUS_TRACKDATA" = "Spotify" ]]
then
echo "--PAUSED--"
PAUSED="1"
else
PAUSED=0
echo "--NOTPAUSED--"
fi
if [[ "$PAUSED" = 0 ]]
then
# || "$XPROP_TRACKDATA" =~ "$DBUS_TRACKDATA" ]]
echo "--NOAD--"
echo "ADMUTE: $ADMUTE"
echo "PAUSED: $PAUSED"
if [[ "$ADMUTE" = "1" ]]
then
sleep 0.5
kill -s TERM "$ALTPID"
for PACTLNR in $(get_pactl_nr); do
pactl set-sink-input-mute "$PACTLNR" no > /dev/null 2>&1
echo "Unmuting sink $PACTLNR"
done
fi
ADMUTE=0
else
echo "--AD--"
echo "ADMUTE: $ADMUTE"
echo "PAUSED: $PAUSED"
if [[ "$ADMUTE" != "1" ]]
then
for PACTLNR in $(get_pactl_nr); do
pactl set-sink-input-mute "$PACTLNR" yes > /dev/null 2>&1
echo "Muting sink $PACTLNR"
done
$PLAYER "$LOOPTRACK" > /dev/null 2>&1 &
ALTPID="$!"
fi
ADMUTE="1"
fi
done
echo "Spotify not active. Exiting."
exit 0
`
I did some changes to the script from @vvsarana:
- Find the window by class instead of a name which changes with a song
- Follow up the window name change to track "Advertisement"
- Removed replacement play, just mutes the Spotify
Enjoy :)
#!/bin/bash
# spotify-automute-simple
# - automatically mute Spotify when ad comes on and loop short track
# - automatically switch back to Spotify when ad over
# Settings
# VAR
ADMUTE=0
PAUSED=0
# FCT
get_pactl_nr(){
pactl list | grep -E '(^Sink Input)|(media.name = \"Spotify\"$)' | cut -d \# -f2 \
| grep -v Spotify
}
# Find window id
WM_ID=$(xdotool search --class "spotify" | sed -n 2p)
# MAIN
xprop -spy -id "$WM_ID" WM_NAME |
while read -r XPROPOUTPUT; do
XPROP_TRACKDATA="$(echo "$XPROPOUTPUT" | cut -d \" -f 2 )"
DBUS_TRACKDATA="$(dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 \
org.freedesktop.DBus.Properties.Get string:'org.mpris.MediaPlayer2.Player' string:'Metadata' | grep xesam:title -A 1 | grep variant | cut -d \" -f 2)"
echo "XPROP: $XPROP_TRACKDATA"
echo "DBUS: $DBUS_TRACKDATA"
if [[ "$DBUS_TRACKDATA" = "Advertisement" ]]
then
echo "--PAUSED--"
PAUSED="1"
else
PAUSED=0
echo "--NOTPAUSED--"
fi
if [[ "$PAUSED" = 0 ]]
then
# || "$XPROP_TRACKDATA" =~ "$DBUS_TRACKDATA" ]]
echo "--NOAD--"
echo "ADMUTE: $ADMUTE"
echo "PAUSED: $PAUSED"
if [[ "$ADMUTE" = "1" ]]
then
sleep 0.5
for PACTLNR in $(get_pactl_nr); do
pactl set-sink-input-mute "$PACTLNR" no > /dev/null 2>&1
echo "Unmuting sink $PACTLNR"
done
fi
ADMUTE=0
else
echo "--AD--"
echo "ADMUTE: $ADMUTE"
echo "PAUSED: $PAUSED"
if [[ "$ADMUTE" != "1" ]]
then
for PACTLNR in $(get_pactl_nr); do
pactl set-sink-input-mute "$PACTLNR" yes > /dev/null 2>&1
echo "Muting sink $PACTLNR"
done
fi
ADMUTE="1"
fi
done
echo "Spotify not active. Exiting."
exit 0
Does anybody here have version 0.8.4 of Spotify for AMD64? I can only find i386 versions.
Hey, @maximvl!
Could you please help me out with your code? I'm new to linux, though I hate commercials.
So, I'm running Xubuntu 18.04.4 and when I try to run your script with spotify already running I get the following mesange:
./spotify-admute.sh: line 20: xdotool: command not found
xprop: error: Invalid window id format: .
Spotify not active. Exiting.
Will be supper grateful for your help.
Maksym
hey, @bim9262
I used the piece of code you suggested in script.
Somehow I ran this script in wrong directory and now spotify has no sound. It does not matter how I launch spotify or how many times I remove and reinstall it.I appreciate any idea that might help.
Try:
num=$(pactl list | grep -E '(^Sink Input)|(media.name = \"Spotify\"$)' | awk '/Spotify/ {print a} {a = $0}' | cut -c 13-)
pactl set-sink-input-mute $num no
Otherwise if you use something gui to control your volume, look at the per application volumes and set Spotify back to a non-zero value.
I add changed some parts of your script @vvsarana and @maximvl.
It captures more ads
#!/bin/bash
# Based on https://gist.github.com/pcworld/3198763
# Mute spotify when it starts advertisement
# Run like this
# nohup bash ~/bin/spotify/mute.sh > /tmp/spotify_mute.log &
# Settings
# VAR
ADMUTE=0
PAUSED=0
# FCT
get_pactl_nr(){
pactl list | grep -E '(^Sink Input)|(media.name = \"Spotify\"$)' | cut -d \# -f2 \
| grep -v Spotify
}
# Find window id
WM_ID=$(xdotool search --class "spotify" | sed -n 2p)
# MAIN
xprop -spy -id "$WM_ID" WM_NAME |
while read -r XPROPOUTPUT; do
XPROP_TRACKDATA="$(echo "$XPROPOUTPUT" | cut -d \" -f 2 )"
DBUS_TRACKDATA="$(dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 \
org.freedesktop.DBus.Properties.Get string:'org.mpris.MediaPlayer2.Player' string:'Metadata' | grep xesam:title -A 1 | grep variant | cut -d \" -f 2)"
echo "XPROP: $XPROP_TRACKDATA"
echo "DBUS: $DBUS_TRACKDATA"
if [[ "$DBUS_TRACKDATA" =~ ^(Advertisement|Spotify)$ ]]
then
echo "--PAUSED--"
PAUSED="1"
else
PAUSED=0
echo "--NOTPAUSED--"
fi
if [[ "$PAUSED" = 0 ]]
then
# || "$XPROP_TRACKDATA" =~ "$DBUS_TRACKDATA" ]]
echo "--NO ADS--"
echo "ADMUTE: $ADMUTE"
echo "PAUSED: $PAUSED"
if [[ "$ADMUTE" = "1" ]]
then
sleep 0.5
num=$(pactl list | grep -E '(^Sink Input)|(media.name = \"Spotify\"$)' | awk '/Spotify/ {print a} {a = $0}' | cut -c 13-)
pactl set-sink-input-mute $num no
echo "UnMuting"
fi
ADMUTE=0
else
echo "--ADS--"
echo "ADMUTE: $ADMUTE"
echo "PAUSED: $PAUSED"
if [[ "$ADMUTE" != "1" ]]
then
num=$(pactl list | grep -E '(^Sink Input)|(media.name = \"Spotify\"$)' | awk '/Spotify/ {print a} {a = $0}' | cut -c 13-)
pactl set-sink-input-mute $num yes
echo "Muting"
fi
ADMUTE="1"
fi
done
echo "Spotify not active. Exiting."
exit 0
Hey guys, thanks for the useful script. As per good open source tradition, I've improved the script and pasting here.
Improvements
- Automatically attaches to Spotify when the player is open. So now you can run this script on system startup and once Spotify is open it attaches to it. When close - detaches. When restarted - attaches to new instance!
- Pause when unmuting (configurable, default = 2 sec)
- New logging (with time, not that verbose)
- Code refactored a little bit
Bugfixes
- Mute didn't work after spotify restart (there were two Spotify sinks)
- When the script was crashed / killed and Spotify was muted, it didn't unmute the Spotify
#!/bin/bash
# Based on https://gist.github.com/pcworld/3198763
# Mute spotify when it starts advertisement
# Run like this
# nohup bash ~/bin/spotify/mute.sh > /tmp/spotify_mute.log &
# Link: https://gist.github.com/pcworld/3198763/af2a4981c6f26075c0a16a261f5294f2cf5e5da5#gistcomment-3384837
# Settings
PAUSE_BEFORE_UNMUTE=2
PAUSE_NOT_ACTIVE=5
# VAR
AD_MUTED=0
AD_DETECTED=0
# FCT
get_pactl_nr() {
pactl list | grep -E '(^Sink Input)|(media.name = \"Spotify\"$)' | cut -d \# -f2 \
| grep -v Spotify
}
mute_player() {
num=$(pactl list | grep -E '(^Sink Input)|(media.name = \"Spotify\"$)' | awk '/Spotify/ {print a} {a = $0}' | cut -c 13- | tail -n 1)
pactl set-sink-input-mute $num yes
}
unmute_player() {
num=$(pactl list | grep -E '(^Sink Input)|(media.name = \"Spotify\"$)' | awk '/Spotify/ {print a} {a = $0}' | cut -c 13- | tail -n 1)
pactl set-sink-input-mute $num no
}
log() {
local line=${1}
echo \[$( date "+%H:%M:%S" )\] $line
}
# Unmute just in case this script crashed the previous time
unmute_player
# Endless loop, sort of service
while [ 1 ]; do
# Find window id
WM_ID=$(xdotool search --class "spotify" | sed -n 2p)
if [ -z "$WM_ID" ]; then
log "Spotify not active"
sleep $PAUSE_NOT_ACTIVE
continue
fi
# MAIN
xprop -spy -id "$WM_ID" WM_NAME |
while read -r XPROPOUTPUT; do
XPROP_TRACKDATA="$(echo "$XPROPOUTPUT" | cut -d \" -f 2 )"
DBUS_TRACKDATA="$(dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 \
org.freedesktop.DBus.Properties.Get string:'org.mpris.MediaPlayer2.Player' string:'Metadata' | grep xesam:title -A 1 | grep variant | cut -d \" -f 2)"
if [[ "$DBUS_TRACKDATA" =~ ^(Advertisement|Spotify)$ ]]; then
log "AD detected"
AD_DETECTED="1"
else
AD_DETECTED="0"
log "No AD detected"
fi
# Debug (uncomment if you need to debug the script)
# echo "XPROP: \"$XPROP_TRACKDATA\""
# echo "DBUS: \"$DBUS_TRACKDATA\""
# echo "Debug: AD_MUTED = $AD_MUTED, AD_DETECTED = $AD_DETECTED"
if [[ "$AD_DETECTED" = "0" ]] && [[ "$AD_MUTED" = "1" ]]; then
log "Unmuting (AD_MUTED = $AD_MUTED, AD_DETECTED = $AD_DETECTED)"
sleep $PAUSE_BEFORE_UNMUTE
unmute_player
AD_MUTED="0"
log "Unmuted"
elif [[ "$AD_DETECTED" = "1" ]] && [[ "$AD_MUTED" = "0" ]]; then
log "Muting (AD_MUTED = $AD_MUTED, AD_DETECTED = $AD_DETECTED)"
mute_player
AD_MUTED="1"
log "Muted"
fi
done
log "Spotify is not active, unmuting"
unmute_player
AD_MUTED="1"
done
log "Something went wrong. Exiting."
exit 1
I've put this to my space too - https://gist.github.com/logical-and/825bab160d604d82bf6ad9ebd3a6410d. Will update there when needed (bugfixes, incompatibilities with Spotify updates)
#!/bin/bash # spotify-automute-simple # - automatically mute Spotify when ad comes on and loop short track # - automatically switch back to Spotify when ad over # Settings PLAYER="mpv --loop=inf" LOOPTRACK="$HOME/Music/Alerts/Jeopardy_loop.mp3" # VAR WMTITLE="Spotify - Linux Preview" ADMUTE=0 PAUSED=0 # FCT get_pactl_nr(){ pactl list | grep -E '(^Sink Input)|(media.name = \"Spotify\"$)' | cut -d \# -f2 \ | grep -v Spotify } # MAIN xprop -spy -name "$WMTITLE" WM_ICON_NAME | while read -r XPROPOUTPUT; do XPROP_TRACKDATA="$(echo "$XPROPOUTPUT" | cut -d \" -f 2 )" DBUS_TRACKDATA="$(dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify / \ org.freedesktop.MediaPlayer2.GetMetadata | grep xesam:title -A 1 | grep variant | cut -d \" -f 2)" echo "XPROP: $XPROP_TRACKDATA" echo "DBUS: $DBUS_TRACKDATA" if [[ "$XPROP_TRACKDATA" = "Spotify" ]] then echo "--PAUSED--" PAUSED="1" else PAUSED=0 echo "--NOTPAUSED--" fi if [[ "$PAUSED" = "1" || "$XPROP_TRACKDATA" =~ "$DBUS_TRACKDATA" ]] then echo "--NOAD--" if [[ "$ADMUTE" = "1" ]] then sleep 0.5 kill -s TERM "$ALTPID" for PACTLNR in $(get_pactl_nr); do pactl set-sink-input-mute "$PACTLNR" no > /dev/null 2>&1 echo "Unmuting sink $PACTLNR" done fi ADMUTE=0 else echo "--AD--" if [[ "$ADMUTE" != "1" ]] then for PACTLNR in $(get_pactl_nr); do pactl set-sink-input-mute "$PACTLNR" yes > /dev/null 2>&1 echo "Muting sink $PACTLNR" done $PLAYER "$LOOPTRACK" > /dev/null 2>&1 & ALTPID="$!" fi ADMUTE=1 fi done echo "Spotify not active. Exiting." exit 0
I'm getting this error Error org.freedesktop.DBus.Error.UnknownMethod: Object does not exist at path “/”
Thank you for your prompt reply, AmpGod! Unfortunately, even with the script you provided, the outcome stays the same: tracks whose titles contain special characters get muted. Maybe there's something wrong I'm doing: I moved the script in the spotify folder and use it to launch the app instead of the default executable O_O