Skip to content

@pcworld /spotify-admute.sh
Last active

Embed URL

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Linux Spotify Ad Mute
#!/bin/bash
#Linux Spotify Ad Mute v2
#Put this script in the directory the "spotify" binary is in (e.g. /usr/share/spotify).
#To open Spotify, run it instead of the "spotify" binary.
#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
#On Debian, you need the package "pulseaudio-utils" for the command line util "pactl" which used in this script
#
#Update: For newer 0.8.x versions (x>4; such as 0.8.8), use this script: https://gist.github.com/pcworld/3198763/#comment-813440
#For 0.9.x: https://gist.github.com/pcworld/3198763/#comment-857143
#
#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 THE 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.
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" # http://stackoverflow.com/a/246128
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 &
$DIR/spotify "$@" &
wait $! &&
test -z "`jobs -p`" || kill `jobs -p` # http://stackoverflow.com/a/2618497
@EDawg878

Thank you so much for this script!

@bim9262

replace the current while loop with the following to mute just spotify. not every application

while read -r line ; do
    num=$(pactl list | grep -E '(^Sink Input)|(media.name = \"Spotify\"$)' | awk '/Spotify/ {print a} {a = $0}' | cut -c 13-)
    if ! [[ "\`dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify / org.freedesktop.MediaPlayer2.GetMetadata\`" == \*'string "mpris:artUrl"'\* ]]
    then
        pactl set-sink-input-mute $num yes
    else
        pactl set-sink-input-mute $num no
    fi
done &
@ghost
Unknown commented

hey, just made an account to say thanks! great script and thanks bim9262 as well. everything works perfectly. if you are new to linux like me you may find you are not able to move the file into the spotify folder because you do not have permission. you can move it with terminal. type:

sudo mv (the directory of the file)/spotify-admute.sh usr/share/spotify

i would like to learn how to add to the script so that it plays music from the default music player when spotify is silent. can anyone point me into the right direction.

thanks again!

@EDawg878

Assuming you are using the Ubuntu distribution, the default player is rhythmbox-client. In the If statement add a command to play then stop music from rhythmbox, for the manual page of rhythmbox use the command: man rhythmbox-client

Similar to bim9262, I spent a long time messing around with pactl to get the same desired effect (muting only Spotify not any other application). I ended up using the script at: http://askubuntu.com/questions/180612/script-to-mute-an-application
Also on a side note I've been able to use icecast to stream the music to my mobile devices

@EDawg878

Just add a line to start the song after the mute

then
pactl set-sink-input-mute $num yes
rhythmbox URL
else
pkill rhythmbox
pactl set-sink-input-mute $num no
fi

Will play an internet radio during the mute and kill it after its over

@sbenkk
while read -r line ; do
    num=$(LANG=C pactl list | grep -E '(^Sink Input)|(media.name = \"Spotify\"$)' | awk '/Spotify/ {print a} {a = $0}' | cut -c 13-)
    if ! [[ "`dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify / org.freedesktop.MediaPlayer2.GetMetadata`" == *'string "mpris:artUrl"'* ]]
    then
        pactl set-sink-input-mute $num yes
    else
        pactl set-sink-input-mute $num no
    fi
done
@chunged

Hi all. This script worked superb for a long while up until I updated to spotify 0.8.8 from 0.8.4. I believe it had difficulty muting/unmuting with the new version.

This is what I use now:

while read -r line ; do
    num=$(LANG=C pactl list | grep -E '(^Sink Input)|(media.name = \"Spotify\"$)' | awk '/Spotify/ {print a} {a = $0}' | cut -c 13-)
    string="`dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify / org.freedesktop.MediaPlayer2.GetMetadata`"
    if [[ $string != *"mpris:artUrl"* && $string == *"mpris:length"* ]]
        then
            pactl set-sink-input-mute $num yes
        else
            pactl set-sink-input-mute $num no
        fi
done &
@MilkaLichtblau

Could you post an ls -al of your spotify-client folder?
The script worked fine for me as well, but I had to reinstall everything after crashing my entire system and the current version installs everything to /opt/spotify/..., not anymore to /usr/share/spotify. So now root owns everything, instead of "user". As far as I remember, it was "user" with the older client version...
Dunno what is the exact problem, but if I put the admute-Script into the /opt/... directory and start it there, my whole graphical environment crashes.

@robbix

high chunged,
did you put the new spotify_block_ads.sh in /usr/bin or in the old /usr/share/spotify/ ?
does it work for you ?
if yes, what is the exactly content of /usr/share/spotify/spotify_block_ads.sh now ?
I have the same problem, muting doesn't work anymore ? I tried with your content.
Thanks in advance !

@EDawg878

chunged, are you sure that it is working with the latest Spotify? I've tried your code but it doesn't mute anymore.

@batdevis

In ubuntu 12.10 I put it on /usr/bin, but doesn't work.

There's this error on terminal output:

ChannelError(0, 1, social_get_popularity)

@pcworld
Owner

Just FYI, I use an old version of Spotify (as I thought the risk of an update breaking this script was too high), that's a reason why I haven't updated this script yet.

(Note: I've added syntax highlighting to some comments, because GitHub otherwise breaks its contents (e.g. the asterisks).)

@Girths

Just signed up to say it now works since the above changes :D

Using Spotify version 0.8.8.323

@smadsen100

Sorry for my ignorance, but I have no idea of how to run this script. I downloaded it, changed it according to AwsomePlunger and moved it to /opt/spotify/spotify-client since I run Ubuntu 13.04 and Spotify client 0.8.8. But how do I run the script? If I double-click the 'spotify-admute.sh' file I just get a file-editor (gedit). Then I tried 'spotify spotify-admute.sh' in a terminal, but this only runs spotify and not the script.

Thank you for your help

@pcworld
Owner

@smadsen100:
First, make the script executable. Either run in terminal:
chmod +x /opt/spotify/spotify-client/spotify-admute.sh (if that's the correct path; the folder must contain the "spotify" binary)
or right-click the file in Nautilus (Ubuntu's default file manager) -> Properties -> Permissions -> Check "Allow executing file as program".
Then, double-clicking it in Nautilus might work.
You can also add a new "launcher" to your desktop environment's application menu, point it to "/opt/spotify/spotify-client/spotify-admute.sh", or, if that doesn't work, set "sh /opt/spotify/spotify-client/spotify-admute.sh" as the command.

Let me know if something wasn't clear or you're having problems.

@wewewe34

anyone can upload the old version of spotify 1:0.8.8.323.gd143501.250-1 ? unfortunately i've upgrade to 0.9 deleting the old one... :(

@sptfydl

spotify-client_0.8.4.103.g9cb177b.260-1_i386.deb (created with dpkg-repack): http://www.load.to/5a1dFYD8Fo/spotify-client_0.8.4.103.g9cb177b.260-1_i386.deb (sha256sum: 9334f5e23e2cd2cfbac147c122a0f009d348af9a3743ba274104b0e9cf743c48)

@pcworld
Owner

@AwsomePlunger:
Thanks for pointing that out. I personally won't work on updating this script for new versions in the near future, I haven't read good things at all about recent Spotify updates on their forums.
But if anyone updates the script, please post it (or a reference to it) here!
The song length is in µs (1µs=10⁻⁶s), so multiply by 10⁶ (or cut off the trailing zeros) and you have the song length in seconds.

@pcworld
Owner

Spotify 0.8.4 crashes for me since today. :( Hope this is only temporary. Am I the only one?

Edit 2013-05-17 12:48 UTC: Works again.

@honigdachs

I have the same issue it crashes on startup deleting the cache and config folders also didn't help. Hopefully it really is only temporary!

@pcworld
Owner

@honigdachs Works again for me :)

@donrudo

Doesn't work with version 0.9.0.133 it looks like this version doesn't update DBUS during the ads.

@pcworld
Owner

@donrudo: See [1] and [2].
If you don't want to update this script, you can e.g. downgrade to Spotify 0.8.4.

@OlegSmelov

I wrote a script that works with the latest version using bits and pieces of code above. Here's the code:

#!/bin/bash

was_paused=0 # if last state was paused
ad=0 # if an ad is probably playing right now

while true; do
    num=$(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
        fi

        ad=0
        pactl set-sink-input-mute $num no
    else
        ad=1
        pactl set-sink-input-mute $num yes
    fi

    if [ "$icon_name" = "Spotify" ]; then
        was_paused=1
    else
        was_paused=0
    fi

    sleep 0.5
done

Here's how it works: spotify window has a property _NET_WM_ICON_NAME, which does get updated with the name of the ad in the latest version (0.9.1.55). DBUS, however, is not updated and stays the same after the song. That means an ad is played right now if the title of the track reported by DBUS is different from the window property. I also added 1 second delay after the ad because of latency issues.

This also means that this script is probably not compatible with previous versions, but don't quote me on this.

Update: I'm releasing my code into the public domain. The parts of this script that I haven't written myself are covered by other licenses.

@pcworld
Owner

@OlegSmelov That's great! Added a link to my scipt's header comment.
Have you considered releasing your script under an open source license?

@OlegSmelov

@pcworld Yeah, sure! I've updated my comment. My code is in the public domain now.

@heisamann

hi, i am running ubuntu 13.04 with spotify 09.05
i tried to use the script of OlegSmelov but failed. the sound mutes after each song!
the ads are not blocked, and when they appear the sound doesn't mute!
any ideas?
thanks

@anupdhml

@heisamann I modified the script and it's working for me. Give it a shot!

#!/bin/bash
# Updated from https://gist.github.com/pcworld/3198763/#comment-857143

was_paused=0 # if last state was paused
ad=0 # if an ad is probably playing right now

while true; do
    num=$(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)
    icon_name=$(xprop -name 'Spotify - Linux Preview' WM_ICON_NAME | awk -F"" '{print $2}' | cut -d \" -f 1)
    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
        fi

        ad=0
        pactl set-sink-input-mute $num no
    else
        ad=1
        pactl set-sink-input-mute $num yes
    fi

    #if [ "$icon_name" = "Spotify" ]; then
    if [ -z "$icon_name" ]; then
        was_paused=1
    else
        was_paused=0
    fi

    sleep 0.5
done
@heisamann

thanks halfwise77!
i copied your script in spotify folder under the name spotify-admute.sh, and made it excutable.
i tried spotify from the terminal, and found out that the sound doesn't mute after each song :)
but, ads does not get muted as well :(
so the script did not function to me.
what confuses me is that i don't see any mentioning of spotify-admute.sh in terminal when i execute spotify.
thanks again

@pcworld
Owner

@heisamann: You have to execute @halfwise77's script manually after starting Spotify.

@heisamann

thanks pcworld, i started spotify, then i excuted halfwise77 script spotify-admute.sh from the terminal. i received this message from terminal:
spotify-admute.sh: 13: spotify-admute.sh: [[: not found

and spotify is completely muted.

@pcworld
Owner

@heisamann: Are you sure the script is running in bash? Try to run it explicitly via bash -c ./spotify-admute.sh.

@heisamann

wow, it worked out using the previous hint of @pcworld.
but i am sure that i am using bash shell. i tried executing spotify-admute.sh before by using:
sh spotify-admute.sh
does it make a difference?
thanks a lot

@heisamann

... and thanks a lot to @halfwise77 and @pcworld

@pcworld
Owner

i tried executing spotify-admute.sh before by using:
sh spotify-admute.sh
does it make a difference?

$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Jul 28  2011 /bin/sh -> bash

Maybe your /bin/sh is linked to something else.
If your terminal runs bash, you should also be able to run the script via ./spotify-admute.sh.

Or add the following to your spotify-admute.sh (as seen in my original script), then you will only have to run that script to start Spotify, and the "ad muter" script will shutdown as soon as Spotify exits:

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" # http://stackoverflow.com/a/246128
$DIR/spotify "$@" &
wait $! &&
test -z "`jobs -p`" || kill `jobs -p` # http://stackoverflow.com/a/2618497

Edit: Put my first line (DIR=…) before @halfwise77's script and change his done to done &, then add my other three remaining lines.

@heisamann

you are right, in my case it is linked to dash not bash:
$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Mar 12 17:35 /bin/sh -> dash

@pcworld
Owner

Spotify 0.8.4 doesn't output any sound when playing, first experienced yesterday (independent of this admute-script). :(

@darknils

tried to use @halfwise77's updated script in combination with @pcworld addon
now i this error message repeatingly in terminal:
"You have to specify a sink input index and a mute boolean"
any advise on it?

@pcworld
Owner

@darknils:
Do you use PulseAudio on your system? Try replacing pactl set-sink-input-mute $num no with pactl set-sink-mute 0 no (same with the "yes" line), however this will mute the whole system volume, and not just Spotify while an ad plays.

@darknils

yes using PulseAudio.
now i don't get the error message but it won't mute either.

also noticed an other error message direct at the start
/opt/spotify/spotify-client/spotify-admute.sh: Line 37: $'\r': command not found

using:
ubuntu 12.04 LTS
spotify 0.9.1.55.gbdd3b79f

these lines are in the spotify-admute.sh

#!/bin/bash
# Updated from https://gist.github.com/pcworld/3198763/#comment-857143

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" # http://stackoverflow.com/a/246128

was_paused=0 # if last state was paused
ad=0 # if an ad is probably playing right now

while true; do
    num=$(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)
    icon_name=$(xprop -name 'Spotify - Linux Preview' WM_ICON_NAME | awk -F"– " '{print $2}' | cut -d \" -f 1)
    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
        fi

        ad=0
        pactl set-sink-mute 0 no
    else
        ad=1
        pactl set-sink-mute 0 yes
    fi

    #if [ "$icon_name" = "Spotify" ]; then
    if [ -z "$icon_name" ]; then
        was_paused=1
    else
        was_paused=0
    fi

    sleep 0.5
done &

$DIR/spotify "$@" &
wait $! &&
test -z "`jobs -p`" || kill `jobs -p` # http://stackoverflow.com/a/2618497
@jakicoll

@darknils
In case you don't use an english locale, extracting $num (which is the pulse-audio id of the spotify sink to mute) might fail, which is why pactl complains about the missing sink.

In my case (german locale) the output of pactl list looks like this:

Sink-Eingabe #13
[...]
Eigenschaften:
                media.role = "music"
                media.name = "Spotify"
                application.name = "Spotify"

With english locale however it looks like this:

Sink Input #13
[...]
        Properties:
                media.role = "music"
                media.name = "Spotify"
                application.name = "Spotify"

In order to use an english locale for pactl only, you can insert "LC_ALL=C" in front of the pactl call:

#Uses english locale, works independent from system locale.
num=$(LC_ALL=C pactl list | grep -E '(^Sink Input)|(media.name = \"Spotify\"$)' | awk '/Spotify/ {print a} {a = $0}' | cut -c 13-)

You could of course also modify the script to extract the sink id from the german text, but the above will work in other countries, too.

#German locale only:
num=$(pactl list | grep -E '(^Sink-Eingabe)|(media.name = \"Spotify\"$)' | awk '/Spotify/ {print a} {a = $0}' | cut -c 15-
@darknils

using german version.
error message now: "Fehlgeschlagen: Entität nicht vorhanden"
and dosn't mute when add is runing

switched to international code line
but still same error message in console

@pcworld
Owner

I tried @OlegSmelov's script and it works fine for me. @halfwise's modification didn't.
For users with a non-English locale, I suggest to put export LANG= at the beginning of the script (after #!/bin/bash).

@AmpGod

Forked halfwise77´s script. This works flawlessly for me.
Oh and mine shouts the title and artist to icecast2 audio broadcaster.
Original script: https://gist.github.com/pcworld/3198763/#comment-873221

Works flawlessly with current spotify-linux.
$ dpkg --list | grep spot
ii spotify-client 1:0.9.1.55.gbdd3b79.203-1 amd64 Spotify desktop client

$ lsb_release -a
Distributor ID: Ubuntu
Description: Ubuntu 12.10
Release: 12.10
Codename: quantal

Instructions on how to make a audio stream server:
http://askubuntu.com/questions/28496/how-do-i-setup-an-icecast-server-for-broadcasting-audio-in-my-network

#!/bin/bash
# Updated from https://gist.github.com/pcworld/3198763/#comment-873221
was_paused=0 # if last state was paused
ad=0 # if an ad is probably playing right now
oldSong=""

IceUser="<IceCast Admin>"
IcePass="<IceCast Password>"
IceMount="%2Fmystream.mp3"
BaseURL="http://localhost:8000/admin/metadata?mount=$IceMount&mode=updinfo&song="

while true; do
    num=$(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)
    icon_name=$(xprop -name 'Spotify - Linux Preview' WM_ICON_NAME | awk -F"– " '{print $2}' | cut -d \" -f 1)
         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_artist=$(echo -n "$META" | grep xesam:artist -A 2 | grep string | grep -v xesam | 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
        fi

        ad=0
        pactl set-sink-input-mute $num no
    else
        ad=1
        pactl set-sink-input-mute $num yes
        song_artist="Spotify"
        song_name="Advert"
    fi

    #if [ "$icon_name" = "Spotify" ]; then
    if [ -z "$icon_name" ]; then
        was_paused=1
    else
        was_paused=0
    fi

    if [[ "$song_name" != "$oldSong" ]]; then
      ## ! Uncomment these after you have a working IceCast stream ! ##
      #Song=$(echo -n "$song_artist - $song_name" | perl -pe's/([^-_.~A-Za-z0-9])/sprintf("%%%02X", ord($1))/seg');
      #echo "$song_artist - $song_name"
      #echo "----> Result:"
      #wget -O - --tries=1 --user=$IceUser --password=$IcePass --auth-no-challenge -q $BaseURL$Song
      #echo "-----------------------------------------------"
      oldSong="$song_name"
    fi
    sleep 0.5
done
@ghost
Unknown commented

I created an executable file based off of the instructions for 13.04 ubuntu, and saved the file in the spotify-client folder. I copied and pasted the suggested block of code which would play a song from rhythmbox during an ad.

I'm running spotify 9.something, the latest from their website at this time. It worked once, and muted for one ad.

Ever since spotify cannot play anything, and rhythmbox produces no sound either. I have uninstalled and reinstalled both spotify and rhythmbox, using synaptic, to no effect. I have deleted the script, to no effect. The script must have changed something deep in the sound settings, permanently. Where should I find these files, and how should I fix them?

I am THIS close to reinstalling my entire OS. this sucks.

EDIT: FIxed my problems using spotify and rhythmbox, but gave up on the ad mute for now.

@ghost
Unknown commented

I'm using Spotify 0.9.4, OlegSmelov's script, Linux Mint 15 x64. Any tips?

Error org.freedesktop.DBus.Error.ServiceUnknown: The name org.mpris.MediaPlayer2.spotify was not provided by any .service files
You have to specify a sink input index and a mute boolean
@mindbreaker

You have to run spotify first @skamlic

Did anyone tried it on kubuntu?

@rhoconlinux

+Skamlic, you should do this to disable the changes:

pactl set-sink-mute 0 no

Cheers,

@DrAxelbauer

He everyone!
I can report, that OlegSmelovs Script works like a charm on my Opensuse Box:
Opensuse x86_64 13.1
Spotify Version: 0.9.1.183

(Just for information for not so mature linux users: Replace the spotify command in your spotify start button with the following command and everytime spotify starts the spotify-admute script will also start:

(spotify &); sh spotify-admute.sh

@k1monfared

Lovely. Thank you all very much.
I tried the first file provided here, with the modification to mute only the spotify and it works on my fedora 18 (fc18.x86_64)
Spotify 0.9.1.55

@zikofv

Working on Ubuntu 12.10 with Spotify 0.9.4.183.
Using OlegSmelov's script with LC_ALL=C inside the $num definition, since i'm using a spanish locale.
Thank you all!

@AmpGod

Somewhat of a update to my blocker, https://gist.github.com/pcworld/3198763/#comment-898010

Works like a charm, with muting and updates icecast with song information - even the special characters are done correctly.

Instructions on how to make a audio stream server:
http://askubuntu.com/questions/28496/how-do-i-setup-an-icecast-server-for-broadcasting-audio-in-my-network

Skamlic https://gist.github.com/pcworld/3198763/#comment-955964
-- This script fixes that problem by retrying the audio channel id getting until we get a valid one.

$ dpkg --list | grep spoti
ii spotify-client 1:0.9.4.183.g644e24e.428-1 amd64 Spotify desktop client

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 13.10
Release: 13.10
Codename: saucy

#!/bin/bash
## Config ##
IceUser="<ICECast Username>"
IcePass="<ICECast Password>"
IceMount="%2Fmystream.mp3" # = /mystream.mp3, the icecast mountpoint to modify
BaseURL="http://localhost:8000/admin/metadata?mount=$IceMount&mode=updinfo&song="
##/Config ##
## Spotify Launch ##
spotify &>/dev/null &
spotiPid=$!
wait=1
while [ $wait = 1 ]; do
  printf "Waiting for spotify...\n"
  sleep 1
  icon=$(xprop -name 'Spotify - Linux Preview' WM_ICON_NAME &>/dev/null)
  if [ $? == 0 ]; then
    wait=0
  fi
done
##/Spotify Launch ##
ad=0
pause=0
lastIcon=""
while true; do
  num=$(pactl list | grep -E '(^Sink Input)|(media.name = \"Spotify\"$)' | awk '/Spotify/ {print a} {a = $0}' | cut -c 13-)
  if [[ "$num" -eq "" ]]; then
    sleep 0.1
    continue;
  fi
  icon_name=$(xprop -name 'Spotify - Linux Preview' WM_ICON_NAME | awk -F\" '{ print $2; }' );
  if [[ -z "$icon_name" ]]; then
    pause=1
    else
    pause=0
  fi
  if [[ "$lastIcon" = "$icon_name" ]]; then
    sleep 0.2
    continue;
  fi
  echo "$icon_name"
  lastIcon="$icon_name"
  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; }')
  if [[ "$song_name" && "$icon_name" =~ "$song_name" ]]; then
    if [ "$pause" -eq 0 -a "$ad" -ne 0 ]; then
      # wait 1 second after a commercial
      sleep 1
    fi
    ad=0
    pactl set-sink-input-mute $num no
  else
    ad=1
    pactl set-sink-input-mute $num yes
    song_artist="Spotify"
    song_name="Advert"
    song_album=""
   fi
    Track="$song_track"
    if [ $song_track -lt 10 ]; then
      Track="0$song_track"
    fi
    if [ $song_cd -ne "0" ]; then
      Track=$((($song_cd * 100) + $song_track))
    fi
    Title="$song_artist [$song_album] $Track - $song_name"
    if [ -z "$song_album" ]; then
      Title="$song_artist - $song_name"
    fi
    #Song=$(echo -n "$Title" | perl -pe's/([^-_.~A-Za-z0-9])/sprintf("%%%02X", ord($1))/seg');
     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');
    echo "Title=$Title"
    echo "Song=$Song"
# !!! Uncomment the following wget line ONLY if you have icecast running !!! #
#    wget -O - --tries=1 --user=$IceUser --password=$IcePass --auth-no-challenge -q $BaseURL$Song
    sleep 0.25
done &

wait $spotiPid &&
test -z "`jobs -p`" || kill `jobs -p`
@cossmo

Hey guys,

I'm running Spotify 0.9.4.183 on ElementaryOS v0.2 "Luna", and out of all the pieces of code listed here, the only one that did the trick for me was:

#!/bin/bash

was_paused=0 # if last state was paused
ad=0 # if an ad is probably playing right now

while true; do
num=$(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
    fi

    ad=0
    pactl set-sink-input-mute $num no
else
    ad=1
    pactl set-sink-input-mute $num yes
fi

if [ "$icon_name" = "Spotify" ]; then
    was_paused=1
else
    was_paused=0
fi

sleep 0.5

done

Unfortunately, whilst it does indeed mute the ads when they come on, it also mutes any tracks that have special characters(i.e. ş,ţ,ă, etc) in their title. It worked fine up until a few weeks ago (meaning it only muted ads), but one day it just started blocking certain tracks as well. Any suggestions ?

I'm sorry I can't give credit to the guy who initially made the above code, but I've tried so many of them, that I forgot whose this one is. And yes, I'm fairly new to the whole linux thing :s

@AmpGod

As a fix/replacement for the script for cossmo ( https://gist.github.com/pcworld/3198763/#comment-1192079 )
Includes a fix for
"You have to specify a sink input index and a mute boolean"

LC_ALL ensures nice, parseable output.

#!/bin/bash
LC_ALL=C
## 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 ##
lastIcon=""
ad=0

xprop -spy -name 'Spotify - Linux Preview' WM_ICON_NAME |
while read -r line ; do
  if [[ ! -d "/proc/$spotiPid" ]]; then
    printf "Spotify exited. Quitting.\n"
    break
  fi
  waitPulse=1
  ## Waiting fo pulseaudio
  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
  icon_name=$(echo "$line" | awk -F\" '{ print $2; }' );
  if [[ "$lastIcon" = "$icon_name" ]]; then
    continue;
  fi
  META=$(dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify / org.freedesktop.MediaPlayer2.GetMetadata)
  song_rating=`echo "$META" | grep xesam:autoRating -A 1 | grep variant | awk '{ printf $3; }'`
  song_name=$(echo -n "$META" | grep xesam:title -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)

  printf "Rating: $song_rating, $icon_name\n"
  mute=1
  if [[ "$song_name" && "$icon_name" =~ "$song_name"  ]]; then
    mute=0
  fi
  if [[ $mute -eq 0 ]]; then
    if [ $ad -eq 1 ]; then #Post-ad sleep
      sleep 0.5
    fi
    pactl set-sink-input-mute $num no
    ad=0
  else
    pactl set-sink-input-mute $num yes
    ad=1
  fi
done

test -z "`jobs -p`" || kill `jobs -p` 2>/dev/null
exit 0
@fernandolguevara

mute spotify ads (only spanish users)

tested on ubuntu 14.04

#!/bin/bash
fg_black="$(tput setaf 0)"
fg_red="$(tput setaf 1)"
fg_green="$(tput setaf 2)"
fg_yellow="$(tput setaf 3)"
fg_blue="$(tput setaf 4)"
fg_magenta="$(tput setaf 5)"
fg_cyan="$(tput setaf 6)"
fg_white="$(tput setaf 7)"
reset="$(tput sgr0)"


pid=$$

ad=0

#for testing  
c=0
cc=-1

while true ; do  
  echo "${fg_white} $pid ${reset}"  

  if [ $c -eq $cc ]; then
    echo "${fg_red} !!STOP!! $c, $cc ${reset}"  
    break
  fi

  c=$(($c+1))

  num=$(pactl list | grep -E '(^Entrada)|(media.name = \"Spotify\"$)' | awk '/Spotify/ {print a} {a = $0}' | cut -c 21-)

  icon_name=$(xprop -name 'Spotify - Linux Preview' WM_ICON_NAME | awk -F\" '{ print $2; }' );


  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_artist=$(echo -n "$META" | grep xesam:artist -A 2 | grep string | grep -v xesam | cut -d \" -f 2)

  mute=1

  echo "${fg_green} $icon_name${reset}"  

  if [[ $icon_name == *$song_artist* ]] 
    then
      echo "${fg_green} Artista OK! ${reset}"
    if [[ $icon_name == *$song_cancion* ]]
      then
        echo "${fg_green} Cancion OK! ${reset}"
        mute=0
      else
        echo "${fg_red} Cancion ERROR! ${reset}"
    fi
  else
    echo "${fg_red} Artista ERROR! ${reset}"
  fi

  sleep 0.5
  if [ $mute -eq 0 ]; then
    if [ $ad=1 ]; then #Post-ad sleep
      sleep 0.5
    fi
    echo "${fg_blue} !NO-MUTE! ${reset}"
    pactl set-sink-input-mute $num no
    ad=0
  else
    echo "${fg_blue} !MUTE! ${reset}"
    pactl set-sink-input-mute $num yes
    ad=1
  fi
done &
@cossmo

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

@bigeebeans

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 :)

@bigeebeans

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 :)

@epleaner

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!

@AmpGod

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
@AugustasV

How to use this script?

@SecUpwN

@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! :smile: @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!

@Feltzer

@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.

@SecUpwN

@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. :smile_cat:

@rhoconlinux

:(
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. :/

@hairyheron

@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 \
@SecUpwN

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! :smiling_imp: LET'S PIMP IT UP!
Proper credit will be given - please tell me ASAP if you have any problem with anything.

@Feltzer

@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.

@aneuronal

@SecUpwN i try it, and work perfectly.
thx very much for a comprehensible installation.

@nmabhinandan

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?

@openpaul

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

@debrandt

@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" ]
@syss

@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" ]
@SecUpwN

:exclamation: 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!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.