# Listen to music on Youtube with the music player daemon



## NapoleonWils0n (May 6, 2020)

Heres how to listen to music on Youtube using the music player daemon,
the w3m browser and a little shell script i wrote called pinch

We use the w3m command line browser and set the pinch script as an external browser,
which we can use run using a keyboard combination in w3m

the pinch script accepts a youtube url and uses youtube-dl to grab the best audio stream,
then uses mpc to send the audio stream to mpd and play it 

I know there are projects like mpsyt 
but unfortunately you now need to create your own google api key to use with mpsyt

Video demo






You need the latest version of youtube-dl installed with pip,
because the freebsd pkg isnt as up to date

Current version of youtube-dl installed with pip:
2020.05.03 

Freebsd pkg:
youtube_dl-2020.01.24 

You dont need to uninstall youtube-dl package if you have it installed,
when we set up youtube-dl with pip programs that use it will use the pip version


Install required packages

+ Install music player daemon, mpc and ncmpc and python37 and py37-pip and w3m


```
# pkg install musicpd musicpc ncmpc python37 py37-pip w3m
```

install youtube_dl with pip

add the python bin to your shell path

add the following code to your ~/.bashrc if uisng bash,
or to your ~/.zshrc file if your are using the zsh shell


```
# home local python bin
if [ -d "$HOME/.local/bin" ]; then
   PATH="$HOME/.local/bin:$PATH"
fi
```

+ source your ~/.bashrc if you are using the bash shell


```
source ~/.bashrc
```

+ or source your ~/.zshrc file in using the zsh shell


```
source ~/.zshrc
```

+ install youtube_dl with pip


```
pip-3.7 install --user youtube_dl
```

when you need to upgrade youtube_dl you would run the following code


```
pip-3.7 install --upgrade --user youtube_dl
```


music player daemon set up

edit the music player config file and add the location of your music directory
replace vi the editor of your choice


```
# vi /usr/local/etc/musicpd.conf
```

edit the musicpd.conf and replace username with your username if the example below


```
music_directory        "/home/username/music"
playlist_directory        "/home/username/.mpd/playlists"
db_file            "/home/username/.mpd/database"
log_file            "/home/username/.mpd/log"
pid_file            "/home/username/.mpd/pid"
state_file            "/home/username/.mpd/state"
sticker_file            "/home/username/.mpd/sticker.sql"

user                "username"
group                "username"

bind_to_address        "/home/username/.mpd/socket"

audio_output {
    type        "oss"
    name        "My OSS Device"
#    device        "/dev/dsp"    # optional
    mixer_type      "hardware"    # optional
    mixer_device    "/dev/mixer"    # optional
#    mixer_control    "PCM"        # optional
    mixer_control    "vol"        # optional
}
```

+ Create the ~/.mpd and ~/.mpd/playlists directories


```
mkdir -p ~/.mpd/playlists
```

+ Create the database,log,pid,state,sticker.sql, and socket


```
touch mpd/{database,log,pid,state,sticker.sql,socket}
```

I wrote a forum post here with a youtube video about setting up bit perfect audio here

Set up your soundcard

List audio devices


```
cat /dev/sndstat
```

the output from my set up with pcm5 as the default output audio device


```
pcm0: <Intel Haswell (HDMI/DP 8ch)> (play)
pcm1: <Cirrus Logic (0x4208) (Analog)> (play/rec)
pcm2: <Cirrus Logic (0x4208) (Analog Headphones)> (play)
pcm3: <Cirrus Logic (0x4208) (Digital)> (play)
pcm5: <USB audio> (play) default
No devices installed from userspace.
```


loader.conf

The next step is to load the audio kernel modules in our /boot/loader.conf

edit you /boot/loader.conf
replace vi with the editor of your choice


```
vi /boot/loader.conf
```

we need to load the audio kernel
by adding snd_hda_load="YES" to /boot/loader.conf


```
snd_hda_load="YES"
```

i have a usb audio dac so i need to add snd_uaudio_load="YES"
to /boot/loader.conf


```
snd_uaudio_load="YES"
```

you only need to add snd_uaudio_load="YES" if you are using a usb audio device


sysctl.conf

We set the default audio output device in /etc/sysctl.conf

check your audio devices by running 


```
cat /dev/sndstat
```

in my case the device i want to use as the default audio device is pcm5

edit your /etc/sysctl.conf
replace vi with the editor of your choice


```
# vi /etc/sysctl.conf
```

set the default audio output device 
and enable bitperfect audio which also requires setting the vchans to 0 on the audio device we are setting up


```
hw.snd.default_unit=5
dev.pcm.5.play.vchans=0
dev.pcm.5.bitperfect=1
```

in the above example i was setting pcm5 as the default output device
if you wanted to set up pcm2 as the default the config would look like this


```
hw.snd.default_unit=2
dev.pcm.2.play.vchans=0
dev.pcm.2.bitperfect=1
```

You can also set the default audio device and bitperfect audio with the sysctl command 


```
# sysctl hw.snd.default_unit=2
# sysctl dev.pcm.2.play.vchans=0
# sysctl dev.pcm.2.bitperfect=1
```


rc.conf

Starting the music player daemon service

To start the music player daemon automatically at login we need to add
musicpd_enable="YES" to our /etc/rc.conf file

you can either edit the rc.conf file manually
or use the sysrc command

to manually edit the /etc/rc.conf 
edit the file with vi or the text editor of your choice


```
# vi /etc/rc.conf
```

and then add the following code and save the file


```
musicpd_enable="YES"
```

or you can use the sysrc command


```
# sysrc musicpd_enable="YES"
```


ncmpc

Setting up the ncmpc mpd client
or you can use any other mpd of your choice

+ create the ncmpc directory in your home


```
mkdir -p ~/.ncmpc
```

+ copy the ncmpc sample config file to the ~/.ncmpc directory you just created


```
cp /usr/local/share/doc/ncmpc/config.sample ~/.ncmpc/config
```

+ edit the ~/.ncmpc config file and add the location of the mpd socket, replace vi with whatever editor you want


```
vi ~/.ncmpc
```

set the mpd host to the location of socket file


```
host = "/home/username/.mpd/socket"
```

replace username with your username

Create a bin directory in your home

The next step is to create a bin directory in your home if you dont have one
if you already have a bin directory set up and added to your shell path you can skip this step


```
mkdir -p ~/bin
```

next you have to add the path to the bin directory to your shell path,
by edting your shells config file like your ~/.bashrc for bash or ~/.zshrc file for the zsh shell

+ bash 


```
vi ~/.bashrc
```

+ zsh


```
vi ~/.zshrc
```

replace vi with whatever editor you want in the above example
then add the following code to add the bin directory to your shell path and save the file


```
if [ -d "$HOME/bin" ]; then
   PATH="$HOME/bin:$PATH"
fi
```

+ you then need to source your ~/.bashrc file if you are using bash


```
source ~/.bashrc
```

+ or if you are using the zsh shell then need to source your ~/.zshrc file


```
source ~/.zshrc
```


Pinch shell script

the pinch shell script takes a youtube url and use youtube-dl to grab best quality audio stream from the video,
and then use mpc to send the url to mpd and play it

pinch shell script on github

+ save the code below into a file called pinch into your ~/bin directory


```
#!/bin/sh

# script usage
usage()
{
echo "\
$(basename "$0") -i url"
exit 2
}

# error messages
INVALID_OPT_ERR='Invalid option:'
REQ_ARG_ERR='requires an argument'
WRONG_ARGS_ERR='wrong number of arguments passed to script'

# if script is run arguments pass and check the options with getopts,
# else display script usage and exit
[ $# -gt 0 ] || usage "${WRONG_ARGS_ERR}"

# getopts check and validate options
while getopts ':i:h' opt
do
  case ${opt} in
     i) infile="${OPTARG}";;
     h) usage;;
     \?) usage "${INVALID_OPT_ERR} ${OPTARG}" 1>&2;;
     :) usage "${INVALID_OPT_ERR} ${OPTARG} ${REQ_ARG_ERR}" 1>&2;;
  esac
done
shift $((OPTIND-1))

# get the audio url
url=$(youtube-dl --no-check-certificate --no-playlist -f bestaudio -g "${infile}")

# yt function
yt () {
    if [ -z "$(mpc current)" ]; then # nothing playing
        if [ -z "$(mpc playlist)" ]; then # playlist empty
           mpc add "${url}"
           mpc play
    else # playlist not empty so clear add url and play
           mpc clear
       mpc add "${url}"
           mpc play
    fi
    else # audio playing insert url and play next
        mpc insert "${url}"
    mpc next
    fi
}

# run the yt function with the url
yt "${url}"
```

+ make the script executable


```
chmod +x ~/bin/pinch
```

you can run the pinch script on the command line 
with the url on single quotes


```
pinch -i 'youtube-url-goes-here'
```


w3m browser

The next step is to set up the pinch script as an external browser with the w3m browser,
this will let us browse youtube on the command line and press a keyboard short cut either on a link in a playlist,
or on the videos page and then send the audio to mpd and play it

+ edit the ~/.w3m/keymap file or create it to set the external browser shortcut key


```
vi ~/.w3m/keymap
```

replace vi with the editor of your choice in the above example
and then add the following code to the ~/.w3m/keymap file and save the file


```
keymap ,-m EXTERN
```

+ edit the ~/.w3m/bookmark.html file or create it if it doesnt exist


```
vi ~/.w3m/bookmark.html
```

replace vi with the editor of your choice in the above example
then add the following code to the ~/.w3m/bookmark.html file and save it

note i have added some search engines as well youtube,
and bbc iplayer and itv which can be played with the mpv video player without needing to login


```
<html><head><title>Bookmarks</title></head>
<META http-equiv='Content-Type' content='text/html; charset=UTF-8'>
<body>
<h1>Bookmarks</h1>
<ul>
<li><a href="https://duckduckgo.com/">DuckDuckgo</a></li>
<li><a href="https://google.com/">Google</a></li>
<li><a href="https://www.youtube.com/">YouTube</a></li>
<li><a href="https://www.bbc.co.uk/iplayer">BBC iPlayer</a>
<li><a href="https://www.itv.com">ITV Player</a>
</ul>
</body>
</html>
```

+ edit the ~/.w3m/config file


```
vi ~/.w3m/config
```

replace vi with the editor of your choice in the above example
then set the external browsers as shown below and save the file


```
extbrowser /usr/local/bin/mpv %s
extbrowser2 /usr/home/username/bin/pinch -i %s
extbrowser3 ~/.local/bin/youtube-dl %s &
```

replace username with your username in the above example


starting the music player daemon

To start the music player daemon we start the service with onestart because we havent rebooted the machine


```
# service musicpd onestart
```

+ update the mpd database

update the music player daemon database using mpc update


```
mpc update
```


Browsing youtube with w3m

+ start w3m with the bookmarks


```
w3m -B
```

then open youtube from the bookmarks link


Launching external browsers with w3m

+ when you are on a videos page

when you are on a videos "page" you can launch an external browser by pressing the number of the external browser and shift m

for example in the ~/.w3m/config we set the following external browsers

1 - mpv
2 - pinch
3 - youtube-dl

so when we are on a videos "page" and we want to send the audio to mpd we can run the pinch script by pressing

2 shift + m

thats 2 then hold shift and press m

that will run the pinch script and use youtube-dl to grab the best quality audio stream from the video and then use mpc to send the audio to mpd and play it

+ if you want to open the video with mpv player

press:

1 shift + m

or for youtube-dl press:

3 shift + m


+ when you are in the search results or in a playlist

to send the audio to mpd we can run the pinch script by pressing

2 esc shift + m

thats 2 then esc then hold shift and press m


+ if you want to open the video with mpv player

press:

1 esc shift + m

or for youtube-dl press:

3 esc shift + m

possible issues

when youtube is updated youtube-dl may stop working and you have to wait a few days for a new version of youtube-dl to fix the issue
the usual error you get with curl and ssl

you can check if a new version of youtube-dl is avaiable by running the following command


```
pip-3.7 install --upgrade --user youtube_dl
```


+ What to do when you get it working

After you manage to send audio from youtube to mpd dad - dancing is compulsory,
although armchair dancing is permitted if you knees have packed in like mine

For extra points posting a video of your dad dancing to the forum would give us all a good laugh

i for one am waiting for sirdice to appear from behind a cloud of bong smoke before saying 
"Tonight Matthew im going to be Beyonce"

Then launching into a chorus of "Uh oh, uh oh, uh oh, oh, no, no" 
while booty shaking in a full suit of armour


----------



## Mjölnir (Jun 7, 2020)

I do like your HOWTO, but IMHO it is too long, and it's structure is not clear to the reader easily -- one has to read all the way through, and build up some kind of structure of all the information oneself.  It would be more attractive if you could compact it's size w/o removing information, and/or distinguish clearer which steps are basically neccessary and what is optional. Plus a visible structure, similar somehow to e.g. the man pages, with an _Examples_ section.


----------



## NapoleonWils0n (Jun 23, 2020)

i updated the pinch script so it now use desktop notifications to display the currently playing song
you need to install dunst for the notifications


```
#!/bin/sh

# script usage
usage()
{
echo "\
$(basename "$0") -i url"
exit 2
}

# error messages
INVALID_OPT_ERR='Invalid option:'
REQ_ARG_ERR='requires an argument'
WRONG_ARGS_ERR='wrong number of arguments passed to script'

# if script is run arguments pass and check the options with getopts,
# else display script usage and exit
[ $# -gt 0 ] || usage "${WRONG_ARGS_ERR}"

# getopts check and validate options
while getopts ':i:h' opt
do
  case ${opt} in
     i) input="${OPTARG}";;
     h) usage;;
     \?) usage "${INVALID_OPT_ERR} ${OPTARG}" 1>&2;;
     :) usage "${INVALID_OPT_ERR} ${OPTARG} ${REQ_ARG_ERR}" 1>&2;;
  esac
done
shift $((OPTIND-1))

# get the audio url and title
url=$(youtube-dl --no-check-certificate --no-playlist -e -f bestaudio -g "${input}")
link=$(echo "${url}" | awk -F' ' '/https:/ {print $1}') # audio url
name=$(echo "${url}" | awk -F'https:' '{print $1}') # name of song

# yt function
yt () {
    if [ -z "$(mpc current)" ]; then # nothing playing
        if [ -z "$(mpc playlist)" ]; then # playlist empty
           mpc add "${link}"
           mpc play
       notify-send "Now Playing ♫" "${name}"
    else # playlist not empty so clear add url and play
           mpc clear
       mpc add "${link}"
           mpc play
       notify-send "Now Playing ♫" "${name}"
    fi
    else # audio playing insert url and play next
        mpc insert "${link}"
    mpc next
    notify-send "Now Playing ♫" "${name}"
    fi
}

# run the yt function with the url
yt "${url}"
```


----------



## NapoleonWils0n (Jun 23, 2020)

mjollnir said:


> I do like your HOWTO, but IMHO it is too long, and it's structure is not clear to the reader easily -- one has to read all the way through, and build up some kind of structure of all the information oneself.  It would be more attractive if you could compact it's size w/o removing information, and/or distinguish clearer which steps are basically neccessary and what is optional. Plus a visible structure, similar somehow to e.g. the man pages, with an _Examples_ section.


I tried to make it as noob friendly as possible so I explained things a more advanced user wouldn't need spelling out.
Always a bit of trade off writing something in baby steps vs just assuming people will know what you are talking about.


----------



## SirDice (Jun 24, 2020)

NapoleonWils0n said:


> Always a bit of trade off writing something in baby steps vs just assuming people will know what you are talking about.


Yep, that's always a bit of a balancing act. It's fine if you assume the reader has some prior knowledge though, just mention it in the first paragraphs so people know what to expect.


----------



## isseeder96 (Oct 2, 2020)

I am unsure how I am meant to find videos with this.  I can type into what resembles a text form above, but I cannot see how to actually "enter" it. 
How do I submit the search?


----------



## NapoleonWils0n (Oct 3, 2020)

isseeder96 said:


> I am unsure how I am meant to find videos with this.  I can type into what resembles a text form above, but I cannot see how to actually "enter" it.
> How do I submit the search?


W3M has stopped working with youtube

i tried changing the user agent in the w3m config but no joy
Maybe its a combination of settings that need to be changed in order for w3m to work with youtube again

Still trying to figure it out


----------



## George (Oct 3, 2020)

Please use dots at the end of a sentence. It makes it easier to read.

Not needing a youtube api key would be really nice.


----------



## Alain De Vos (Oct 3, 2020)

How does it fits in the business model of youtube ?
I mean without ads, youtube just is informed of their api's used ?


----------



## NapoleonWils0n (Oct 3, 2020)

Elazar said:


> Please use dots at the end of a sentence. It makes it easier to read.


Hi Mate

Like morse code
Your proper old school


----------



## isseeder96 (Oct 4, 2020)

NapoleonWils0n said:


> W3M has stopped working with youtube
> 
> i tried changing the user agent in the w3m config but no joy
> Maybe its a combination of settings that need to be changed in order for w3m to work with youtube again
> ...



Why does it have to be youtube? One could write up a simple meta search engine for youtube or use an existing one, I think a few exist... I'll look


----------



## isseeder96 (Oct 4, 2020)

Nevermind I think they have dissapeared off the face of the earth.
Used to be a couple of youtube meta search engines, they let you search youtube videos on their site the neither embedded them or redirected you. Usually worked without js. 
We can't have nice things.


----------



## isseeder96 (Oct 11, 2020)

Hey everyone, I have sort of good news. I found this project! 









						GitHub - user234683/youtube-local: browser-based client for watching Youtube anonymously and with greater page performance
					

browser-based client for watching Youtube anonymously and with greater page performance - GitHub - user234683/youtube-local: browser-based client for watching Youtube anonymously and with greater p...




					github.com
				




It lets you host a light weight youtube mirror locally and from what I can see it does not require an API key as it interacts with youtube the right way. 
It works in w3m, although its kind of ugly and not optimal but it works you can search and open results. Pinch will need to be edited I think, I had to stretch my terminal just for it all to fit though which I am not happy about. 




Try to ignore my awful font rendering I am on linux at the moment.

edit: its really easy to edit out images and other stuff that make this a pain to view in w3m


----------



## JaydeTalbot (Feb 4, 2021)

Thanks for such detailed tutorial, I was looking for something like that


----------



## sidetone (May 26, 2022)

That's informative.

Bold text for headers can help with readability. Also, a lot of typing can be saved by writing the file/directory, then using a code box. Each time, there's repeated descriptions on how to edit files.

The information about bitperfect is great. Setting that up is good information to keep in a howto like this.

```
dev.pcm.2.play.vchans=0
dev.pcm.2.bitperfect=1
```
That part is good. The alternate example for those bitperfect settings on a different default sound card is also good. I like how the usb audio output as needing to be enabled for that device is mentioned, because not everyone knows to look for that special hardware device. Mentioning the device driver may be enough.

Some parts are repetitive for different shells, or simple descriptions would do in place of additional examples. For instance, the `sysctl` command can be used to enable those settings immediately, by using the same arguments as in the file.


----------

