alexherbo2 / krabby

A keyboard interface to the web, inspired by Kakoune
https://krabby.netlify.app
The Unlicense
310 stars 20 forks source link

mpv does not work by default on Vivaldi >3.0 or when using "proprietary media codecs" (libffmpeg.so) #19

Closed SeerLite closed 4 years ago

SeerLite commented 4 years ago

I'm using the default configuration. Browser: Vivaldi (I can reproduce it in Chromium) OS: Arch Linux I tried all the mpv commands listed here in their corresponding context. mpv doesn't open, and the Shell extension shows an error in vivaldi://extensions.

Error in event handler: Error: Attempting to use a disconnected port object Context _generated_background_page.html Stack Trace src/background.js:10 (anonymous function)

const shell = {}
shell.port = chrome.runtime.connectNative('shell')
chrome.runtime.onConnectExternal.addListener((port) => {
  // Send request to the application
  port.onMessage.addListener((request) => {
    shell.port.postMessage(request)
  })
  // Receive response
  shell.port.onMessage.addListener((response) => {
>   port.postMessage(response)   <
  })
})

^The line I enclosed in >/< is highlighted. Is this error relevant to mpv not opening or is it just a coincidence? It seemed to appear everytime I tried mpv bindings.

Thank you so much for Krabby! I'm loving the extension so far.

alexherbo2 commented 4 years ago

Do you have the shell extension actually installed?

SeerLite commented 4 years ago

I'm pretty sure I installed it correctly. I loaded all the extensions that showed up during make. Also, the error appears under the Shell extension, not Krabby.

Here's a screenshot: image

alexherbo2 commented 4 years ago

Yes, but the native manifest / application might not be correctly installed. I know some users skipped the host installation step.

Can you show me the content of the native manifest, and try to run the application from the command-line?

SeerLite commented 4 years ago

Alright, I fixed the issue for Chromium. I think I understand now: The Krabby Makefile does this step automatically but only for Chromium, Chrome and Firefox. I might have messed up the installation when I tried to reproduce it on Chrome and that's why it happened there too.

Still, Vivaldi doesn't seem to work no matter what. I copied ~/.config/chromium/NativeMessagingHosts/shell.json over to ~/.config/vivaldi/NativeMessagingHosts/shell.json. This is the manifest you're talking about, right? Is this what I should be doing? There seems to be no entry for Vivaldi in the host Makefile.

After doing that I restarted Vivaldi but the error remains. Is the Shell extension just not compatible with Vivaldi or am I doing something wrong?

Edit: Is the Shell extension also responsible for invoking the editor from the Editor extension or is that completely unrelated? That function works correctly and invokes whatever I set the editor to.

Edit 2: Just to answer your questions in case they're still relevant: This is shell.json which I assume is the manifest you're referring to:

{
  "name": "shell",
  "description": "Native messaging host to execute external commands",
  "path": "/home/seerlite/.config/krabby/extensions/shell/host/bin/chrome-shell",
  "type": "stdio",
  "allowed_origins": [
    "chrome-extension://ohgecdnlcckpfnhjepfdcdgcfgebkdgl/"
  ]
}

Running the binary set in path from the command line just hangs indefinitely. Is that expected?

alexherbo2 commented 4 years ago

Native messaging does work for me on Vivaldi. Vivaldi does not have a specific location for the manifest; it does use the Chromium one.


The shell extension is responsible of end features for Krabby (running external commands of your liking, such as mpv) and extensions, such as dmenu, editor.


It is expected to hang; chrome-shell.cr reads messages from stdin.

alexherbo2 commented 4 years ago

@SeerLite I can help you on IRC if you want.

https://webchat.freenode.net/#krabby

SeerLite commented 4 years ago

I found the cause of the issue! Thank you so much for explaining how to set up the debug script through bindings! Vivaldi populates LD_PRELOAD with its own libffmpeg.so. This causes my system's ffmpeg to segfault. Unsetting LD_PRELOAD through an mpv wrapper works as a workaround.

I guess you couldn't reproduce it because you don't have the proprietary codecs set up in Vivaldi, so LD_PRELOAD has no effect.

Edit: It looks like the latest version of Vivaldi sets up the ffmpeg codecs automatically on the second restart. They should be located in ~/.local/lib/vivaldi/media-codecs<...>/. I don't know what version of Vivaldi you tested though.

Edit 2: I think the only fix here is to clear the LD_PRELOAD environment variable for mpv. Is this possible through the configuration file or is a wrapper necessary?

alexherbo2 commented 4 years ago

krabby/web/krabby.js and krabby/extension/extension.js define krabby.commands.mpv and krabby.commands.mpvResume functions. The functions are used for the mpv commands. You can overload the functions to call your own command.

Here is a minimal example configuration:

~/.config/krabby/config.js

const { extensions, commands } = krabby
const { shell } = extensions

commands.mpv = ({ selections, callback = (link) => link.href, reverse = false } = {}) => {
  const playlist = commands.getElements(selections).map(callback)
  if (reverse) {
    playlist.reverse()
  }
  shell.port.postMessage({
    command: 'mpv',
    arguments: playlist,
    environment: {
      LD_PRELOAD: ''
    }
  })
}

Instructions:

  1. cd ~/.config/krabby
  2. make
  3. Reload the extension.

Here are some links, so that you can figure out how things work:

SeerLite commented 4 years ago

Alright, thank you so much for the example! It all works fine now :)

Should I close the issue now? I'm still not sure if it's just me having this Vivaldi issue. I'm gonna set up a VM and see if the issue is present on other distros. If so, maybe it should be noted somewhere that Vivaldi may not be fully compatible with mpv commands by default, and that a configuration like this one should be applied?

Again, thank you so much for both the help and the extension itself! It works perfectly and I like it a lot!

alexherbo2 commented 4 years ago

If it can help:

vivaldi
'Proprietary media' support is not installed.  Fix this by running:
    /nix/store/pq3r9kmchbk6nb9js94a8bmjjrbani42-vivaldi-2.11.1811.44-1/opt/vivaldi/update-ffmpeg
The Widevine CDM is not installed.  Fix this by running:
    /nix/store/pq3r9kmchbk6nb9js94a8bmjjrbani42-vivaldi-2.11.1811.44-1/opt/vivaldi/update-widevine

vivaldi --version
Vivaldi 2.11.1811.44
alexherbo2 commented 4 years ago

@SeerLite It could be nice to have a Troubleshooting document.

We can also rename the issue with a more fitting description.

SeerLite commented 4 years ago

Ah I see, so it is something with the old version after all. This is what I get on a fresh run: (TL;DR: 3 restarts required for Vivaldi to set up all proprietary stuff automatically on latest version)

$ vivaldi-stable --version
Vivaldi 3.0.1874.23

$ ls ~/.local/lib/vivaldi
ls: cannot access '/home/seerlite/.local/lib/vivaldi': No such file or directory

$ vivaldi-stable
'Proprietary media' support is not installed. Attempting to fix this for the next restart.
The Widevine CDM is not installed. Attempting to fix this for the next restart.
<...>

$ ls ~/.local/lib/vivaldi
media-codecs-80.0.3987.149

$ vivaldi-stable
The Widevine CDM is not installed. Attempting to fix this for the next restart.
<...>

$ ls ~/.local/lib/vivaldi
media-codecs-80.0.3987.149  WidevineCdm

$ vivaldi-stable
<...>

<...> being unrelated regular debug output.

SeerLite commented 4 years ago

A troubleshooting document sounds nice. Should I provide any more details? I think it's also worth noting that technically not every version of ffmpeg should be affected by the linked libffmpeg. Their versions might match up in some cases AFAIK (I might be wrong).

alexherbo2 commented 4 years ago

I’m not sure about the details. You are best suited, as you are using Vivaldi.

Can I let you write the Troubleshooting entry?

SeerLite commented 4 years ago

Alright haha. Just want to note that this is the first time I do anything like this. Should I fork, create the doc and do a pull request?

SeerLite commented 4 years ago

Hey, I used your example and managed to somewhat override krabby.commands.mpv and krabby.commands.mpvResume. As far as I understand, this is by communicating directly with the Shell extension through the API, right? This is what my config.js looks like. Did I do it correctly?

const { extensions, commands, settings } = krabby
const { shell } = extensions
const { plumb } = commands

commands.mpv = ({ selections, callback = (link) => link.href, reverse = false } = {}) => {
  const playlist = commands.getElements(selections).map(callback)
  if (reverse) {
    playlist.reverse()
  }
  shell.port.postMessage({
    command: 'mpv',
    arguments: [...settings['mpv-config'], ...playlist],
    environment: {
      LD_PRELOAD: ''
    }
  })
}

commands.mpvResume = () => {
  const media = commands.player().media
  media.pause()
  shell.port.postMessage({
      command: 'mpv',
      arguments: [...settings['mpv-config'], location.href, '-start', media.currentTime.toString()],
      environment: {
        LD_PRELOAD: ''
      }
  })
}

Edit: I just realized I left a console.log there. I removed it now.

This overrides the mpv commands for every context except for Document, in which case the default mpv command runs instead. (this is e.g. when pressing m on a YouTube page in Document context).

I'm kind of confused though. As you said, krabby.commands.mpv and krabby.commands.mpvResume are defined both in krabby/web/krabby.js and in krabby/extension/extension.js. I also see that they use different implementations. One uses plumb while the other one uses shell. What's the difference between the two? Is this why the override doesn't work for the Document context? Why are these two definitions necesary in the first place?

Sorry if the questions are dumb. I'm just now kind of starting to understand javascript, and I don't really know how the extension/browser works in depth.

I'll gladly set up the Troubleshooting doc if I manage to fix this issue globally.

alexherbo2 commented 4 years ago

krabby/web/krabby.js is the base object.

It is used in krabby.netlify.app and for the surf support. The plumb method copies JSON messages (for example, mpv commands) to your clipboard. It is left to you to do something with that message; you can open mpv, etc.


krabby/extension/extension.js is the WebExtension part.

It is used in Chrome (Chromium-based) and Firefox browsers. It inherits from the base object.


Example – Plumbing

Copy to your clipboard:

["mpv", "https://youtu.be/4FbQre9VQLI"]

Run the plumb command:

plumb mpv

Take a look at the manifest files and init.js in the web and extension directories.

SeerLite commented 4 years ago

Ok so if I understood correctly then I should only really care about the shell implementation of the commands, right?

Also, I now see why m doesn't work in Document context: the Document mapping calls the shell extension directly, instead of using commands.mpv.

Would the correct way to implement the work-around be to also override that mapping so that it uses commands.mpv instead?

alexherbo2 commented 4 years ago

How about adding mpv-environment setting?

SeerLite commented 4 years ago

...That sounds a lot more straight forward, yeah. Is it easy to implement?

alexherbo2 commented 4 years ago

Yes. Just add settings['mpv-environment'] and call that.

On the user side, the config will look like:

~/.config/krabby/config.js

const { settings } = krabby

settings['mpv-environment'] = {
  LD_PRELOAD: ''
}
SeerLite commented 4 years ago

Nice! That sounds perfect!