NixOS / nixpkgs

Nix Packages collection & NixOS
MIT License
18.4k stars 14.35k forks source link

Firefox missing Narrate feature #78880

Closed jtojnar closed 1 year ago

jtojnar commented 4 years ago

When opening a web page in reader mode, there is supposed to be Narrate button but I see no such thing. I tried installing speechd but that does not seem to be enough. Maybe https://github.com/NixOS/nixpkgs/issues/39500 is needed?

jtojnar commented 4 years ago

Hmm, apparently it needs to be built with speechd support:

https://salsa.debian.org/mozilla-team/firefox/blob/43662dc37d3a4ee1d372ff6fd3edd6123da0b668/dom/media/webspeech/synth/moz.build#L57-58

jtojnar commented 4 years ago

Looks like it is actually building with speechd support when using GTK:

https://salsa.debian.org/mozilla-team/firefox/blob/43662dc37d3a4ee1d372ff6fd3edd6123da0b668/toolkit/moz.configure#L771-784

We might need to use hardcode the path to speechd library:

https://salsa.debian.org/mozilla-team/firefox/blob/43662dc37d3a4ee1d372ff6fd3edd6123da0b668/dom/media/webspeech/synth/speechd/SpeechDispatcherService.cpp#L321

jtojnar commented 4 years ago

When run using env LD_LIBRARY_PATH=$(nix-build -A speechd --no-out-link)/lib firefox, the Narrator works.

stale[bot] commented 4 years ago

Hello, I'm a bot and I thank you in the name of the community for opening this issue.

To help our human contributors focus on the most-relevant reports, I check up on old issues to see if they're still relevant. This issue has had no activity for 180 days, and so I marked it as stale, but you can rest assured it will never be closed by a non-human.

The community would appreciate your effort in checking if the issue is still valid. If it isn't, please close it.

If the issue persists, and you'd like to remove the stale label, you simply need to leave a comment. Your comment can be as simple as "still important to me". If you'd like it to get more attention, you can ask for help by searching for maintainers and people that previously touched related code and @ mention them in a comment. You can use Git blame or GitHub's web interface on the relevant files to find them.

Lastly, you can always ask for help at our Discourse Forum or at #nixos' IRC channel.

anilanar commented 2 years ago

still important to me

taku0 commented 2 years ago

env LD_LIBRARY_PATH=$(nix-build -A speechd --no-out-link)/lib firefox don't show Narrator button. Also, speechSynthesis.getVoices() returns [].

jtojnar commented 2 years ago

I can confirm it does not work any more.

Running with NSPR_LOG_MODULES=all:5 NSPR_LOG_FILE=moz.log env vars does log

Loaded library libspeechd.so.2 (load lib)

but no other message I would expect from the source code:

https://salsa.debian.org/mozilla-team/firefox/-/blob/debian/95.0.1-1/dom/media/webspeech/synth/speechd/SpeechDispatcherService.cpp#L321-352

Or maybe NSPR logging is disabled at build time?

jtojnar commented 2 years ago

The source code between https://salsa.debian.org/mozilla-team/firefox/blob/43662dc37d3a4ee1d372ff6fd3edd6123da0b668/dom/media/webspeech/synth/speechd/SpeechDispatcherService.cpp https://salsa.debian.org/mozilla-team/firefox/-/blob/debian/95.0.1-1/dom/media/webspeech/synth/speechd/SpeechDispatcherService.cpp and is basically the same.

I tried enabling debugging with the following patch:

--- a/pkgs/development/libraries/speechd/default.nix
+++ b/pkgs/development/libraries/speechd/default.nix
@@ -107,6 +107,8 @@ in stdenv.mkDerivation rec {
     # ++ optional withIvona "--with-ivona"
   ;

+  NIX_CFLAGS_COMPILE = "-DLIBSPEECHD_DEBUG=1";
+
   postPatch = ''
     substituteInPlace config/speechd.conf --replace "DefaultModule espeak" "DefaultModule ${selectedDefaultModule}"
     substituteInPlace src/modules/pico.c --replace "/usr/share/pico/lang" "${svox}/share/pico/lang"

And it indeed looks promissing:

Debugging started
Initializing threads, condition variables and mutexes...
Executing command wo_mutex
Inside execute_command_with_reply
Inside spd_send_data_wo_mutex
Writing to socket
Getting reply in spd_events_handler
Written to socket
>> : |SET SELF CLIENT_NAME "who:firefox:web speech api"
|
Waiting for cond_reply_ready in spd_send_data_wo_mutex
<< : |208 OK CLIENT NAME SET
|

spd_send_data:  reply: 208 OK CLIENT NAME SET

ret_ok: err_code:   |208|

Condition for cond_reply_ready satisfied
Reading the reply in spd_send_data_wo_mutex threaded mode
<< : |208 OK CLIENT NAME SET
|

Returning from spd_send_data_wo_mutex
spd_send_data:  reply: 208 OK CLIENT NAME SET

ret_ok: err_code:   |208|

Getting reply in spd_events_handler
Inside execute_command_with_reply
Inside spd_send_data_wo_mutex
Writing to socket
Written to socket
>> : |LIST SYNTHESIS_VOICES
|
Waiting for cond_reply_ready in spd_send_data_wo_mutex
<< : |321 ERR MODULE CANT REPORT VOICES
|

spd_send_data:  reply: 321 ERR MODULE CANT REPORT VOICES

ret_ok: err_code:   |321|

Condition for cond_reply_ready satisfied
Reading the reply in spd_send_data_wo_mutex threaded mode
<< : |321 ERR MODULE CANT REPORT VOICES
|

Returning from spd_send_data_wo_mutex
spd_send_data:  reply: 321 ERR MODULE CANT REPORT VOICES

ret_ok: err_code:   |321|

spd_send_data:  reply: 321 ERR MODULE CANT REPORT VOICES

ret_ok: err_code:   |321|

Executing command wo_mutex
Inside execute_command_with_reply
Inside spd_send_data_wo_mutex
Writing to socket
Getting reply in spd_events_handler
Written to socket
>> : |SET SELF NOTIFICATION begin on
|
Waiting for cond_reply_ready in spd_send_data_wo_mutex
<< : |220 OK NOTIFICATION SET
|

spd_send_data:  reply: 220 OK NOTIFICATION SET

ret_ok: err_code:   |220|

Condition for cond_reply_ready satisfied
Reading the reply in spd_send_data_wo_mutex threaded mode
<< : |220 OK NOTIFICATION SET
|

Getting reply in spd_events_handler
Returning from spd_send_data_wo_mutex
spd_send_data:  reply: 220 OK NOTIFICATION SET

ret_ok: err_code:   |220|

Executing command wo_mutex
Inside execute_command_with_reply
Inside spd_send_data_wo_mutex
Writing to socket
Written to socket
>> : |SET SELF NOTIFICATION all on
|
Waiting for cond_reply_ready in spd_send_data_wo_mutex
<< : |220 OK NOTIFICATION SET
|

spd_send_data:  reply: 220 OK NOTIFICATION SET

ret_ok: err_code:   |220|

Condition for cond_reply_ready satisfied
Reading the reply in spd_send_data_wo_mutex threaded mode
<< : |220 OK NOTIFICATION SET
|

Returning from spd_send_data_wo_mutex
spd_send_data:  reply: 220 OK NOTIFICATION SET

ret_ok: err_code:   |220|

Executing command wo_mutex
Inside execute_command_with_reply
Inside spd_send_data_wo_mutex
Writing to socket
Getting reply in spd_events_handler
Written to socket
>> : |SET SELF NOTIFICATION end on
|
Waiting for cond_reply_ready in spd_send_data_wo_mutex
<< : |220 OK NOTIFICATION SET
|

spd_send_data:  reply: 220 OK NOTIFICATION SET

ret_ok: err_code:   |220|

Condition for cond_reply_ready satisfied
Reading the reply in spd_send_data_wo_mutex threaded mode
<< : |220 OK NOTIFICATION SET
|

Returning from spd_send_data_wo_mutex
spd_send_data:  reply: 220 OK NOTIFICATION SET

ret_ok: err_code:   |220|

Executing command wo_mutex
Inside execute_command_with_reply
Getting reply in spd_events_handler
Inside spd_send_data_wo_mutex
Writing to socket
Written to socket
>> : |SET SELF NOTIFICATION all on
|
Waiting for cond_reply_ready in spd_send_data_wo_mutex
<< : |220 OK NOTIFICATION SET
|

spd_send_data:  reply: 220 OK NOTIFICATION SET

ret_ok: err_code:   |220|

Condition for cond_reply_ready satisfied
Reading the reply in spd_send_data_wo_mutex threaded mode
<< : |220 OK NOTIFICATION SET
|

Returning from spd_send_data_wo_mutex
spd_send_data:  reply: 220 OK NOTIFICATION SET

ret_ok: err_code:   |220|

Executing command wo_mutex
Inside execute_command_with_reply
Inside spd_send_data_wo_mutex
Writing to socket
Getting reply in spd_events_handler
Written to socket
>> : |SET SELF NOTIFICATION cancel on
|
Waiting for cond_reply_ready in spd_send_data_wo_mutex
<< : |220 OK NOTIFICATION SET
|

spd_send_data:  reply: 220 OK NOTIFICATION SET

ret_ok: err_code:   |220|

Condition for cond_reply_ready satisfied
Reading the reply in spd_send_data_wo_mutex threaded mode
<< : |220 OK NOTIFICATION SET
|

Getting reply in spd_events_handler
Returning from spd_send_data_wo_mutex
spd_send_data:  reply: 220 OK NOTIFICATION SET

ret_ok: err_code:   |220|

Executing command wo_mutex
Inside execute_command_with_reply
Inside spd_send_data_wo_mutex
Writing to socket
Written to socket
>> : |SET SELF NOTIFICATION all on
|
Waiting for cond_reply_ready in spd_send_data_wo_mutex
<< : |220 OK NOTIFICATION SET
|

spd_send_data:  reply: 220 OK NOTIFICATION SET

ret_ok: err_code:   |220|

Condition for cond_reply_ready satisfied
Reading the reply in spd_send_data_wo_mutex threaded mode
<< : |220 OK NOTIFICATION SET
|

Returning from spd_send_data_wo_mutex
spd_send_data:  reply: 220 OK NOTIFICATION SET

ret_ok: err_code:   |220|

Getting reply in spd_events_handler
jtojnar commented 2 years ago

So if someone could find out why 321 ERR MODULE CANT REPORT VOICES occurs, that would be helpful. Maybe by digging through the speechd source code. Or by trying speechd from Nixpkgs repo at the time it worked. Check its expression as well. Possibly it is connected with espeak-ng or mbrola backend changes. But $(nix-build -A speechd --no-out-link)/bin/spd-say "Hello word! I am testing the speech dispatcher output modules." does work so not everything is borked.

anilanar commented 2 years ago
> spd-say -L
Failed to get voice list.

> spd-say -O
OUTPUT MODULES
espeak-ng
pico
flite

> spd-say -o espeak-ng -L
# Prints a lot of voices

> spd-say -o pico -L
# Prints few voices

> spd-say -o flite -L
# Prints NO voices

So I assume firefox must be using an output module that is not available.

jtojnar commented 2 years ago

That sounds consistent with

> spd-say -L
Failed to get voice list.

But it is weird that it speaks even without -o flag.

anilanar commented 2 years ago

Found something funny in my home directory .config, which is created by my nix configuration because it's read only:

At ~/.config/speech-dispatcher/speechd.conf

DefaultModule espeak-ng-ng
jtojnar commented 2 years ago

It sounds like it defaults to flite even though it should default to espeak-ng:

https://github.com/NixOS/nixpkgs/blob/d61332c196f5f586876df166e58af7ce975fda4b/pkgs/development/libraries/speechd/default.nix#L31-L34

Something is indeed fishy.

jtojnar commented 2 years ago

Oh, they changed the default:

https://github.com/brailcom/speechd/commit/74be3bf84e74f27a3c601c1c9628922fe9ec404e

which broke our replacement:

https://github.com/NixOS/nixpkgs/blob/d61332c196f5f586876df166e58af7ce975fda4b/pkgs/development/libraries/speechd/default.nix#L111

anilanar commented 2 years ago

Or maybe to espeak-ng-ng:

> spd-say -o espeak-ng-ng -L 
Failed to get voice list.

Maybe this line is the culprit:

https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/libraries/speechd/default.nix#L111

jtojnar commented 2 years ago

Yeah, that is an invalid module so it falls back to flite as we observed. The fact that festival returns no voices is also weird, opened https://github.com/NixOS/nixpkgs/issues/153467 for that, but fixing the speechd package is more important.

anilanar commented 2 years ago

@jtojnar Does the firefox nixpkg still need a change?

After I manually fix the config:

> spd-say -L
# Lists all voices correctly from espeak-ng

But firefox still has empty voice list at http://mdn.github.io/web-speech-api/speak-easy-synthesis/

jtojnar commented 2 years ago

We should probably update speechd to use https://github.com/brailcom/speechd/commit/e14bb268de41cb5e953825e7ab81fe8415a78a2a

jtojnar commented 2 years ago

But I can confirm this patch fixes the Narrate feature:

--- a/pkgs/development/libraries/speechd/default.nix
+++ b/pkgs/development/libraries/speechd/default.nix
@@ -107,8 +107,10 @@ in stdenv.mkDerivation rec {
     # ++ optional withIvona "--with-ivona"
   ;

+  NIX_CFLAGS_COMPILE = "-DLIBSPEECHD_DEBUG=1";
+
   postPatch = ''
-    substituteInPlace config/speechd.conf --replace "DefaultModule espeak" "DefaultModule ${selectedDefaultModule}"
+    substituteInPlace config/speechd.conf --replace "DefaultModule espeak-ng" "DefaultModule ${selectedDefaultModule}"
     substituteInPlace src/modules/pico.c --replace "/usr/share/pico/lang" "${svox}/share/pico/lang"
   ''; 

And I do have a very long list of languages on http://mdn.github.io/web-speech-api/speak-easy-synthesis/.

jtojnar commented 2 years ago

I used env NSPR_LOG_MODULES=all:5 NSPR_LOG_FILE=moz.log LD_LIBRARY_PATH=(nix-build -A speechd --no-out-link)/lib firefox --no-remote -p for the testing (run in Nixpkgs with the patched speechd).

anilanar commented 2 years ago

I confirm that it works, thanks.

nixos-discourse commented 2 years ago

This issue has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/no-tts-in-reader-mode-in-firefox/19475/2

nixos-discourse commented 2 years ago

This issue has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/no-tts-in-reader-mode-in-firefox/19475/3

pinage404 commented 1 year ago

This works for me :

LD_LIBRARY_PATH=$(dirname $(dirname $(realpath $(which spd-say))))/lib firefox -p '' 'https://mdn.github.io/dom-examples/web-speech-api/speak-easy-synthesis/'

The page shows a select with the same voices that are listed with this command

spd-say -o pico -L

When i want text to speech, i have to stop Firefox, and restart it manually with the first command


I would like to permanently fix Firefox

{ pkgs
, ...
}:

{
  home.packages = [
    pkgs.speechd

    # some dark magic Nix stuff here
    (pkgs.firefox.override {
      # the equivalent to
      # LD_LIBRARY_PATH = "$(dirname $(dirname $(realpath $(which spd-say))))/lib";
    })
  ];
}

How to do that ?