openstenoproject/plover

Add a specific dictionary syntax to play a wav audiofile

Opened this issue · 25 comments

DESCRIPTION:
Some professional cat softwares (Eclipse) have a specific syntax to associate a definition when playing an audio file, for example: {w: filename.wav}.

This function can be used, for example, to ask the witness to repeat a word that is not well understood, or to slow down the speech to allow it to be better written.

In the case of Plover, in addition to these uses, this function could be applied both for educational purposes and in the case of devices designed for people with disabilities. For example, in the didactic field, by associating the main keyboard combinations to specific audio files that reproduce their sound, the apprentice can have an immediate confirmation of the correctness of the keys pressed without looking at the screen but concentrating only on the keyboard. In the field of disabilities it is possible to create specific dictionaries of syllables associated with their respective phonemes. In this way, for example, a person with speech disabilities could use the steno machine to "speak" at normal speed just writing each syllable of the words, so without the need to learn any abbreviation, or a blind person could use the shorthand machine while also receiving a syllabic feedback.

ALTERNATIVE SOLUTIONS CONSIDERED:
It is possible to obtain a similar result by associating the Plover output to a speech to text software. However, this solution is less flexible because most of these software are structured to work on words and not with syllables or single letters, so with the latter they can produce not correct audio results. Furthermore to write words with Plover it is necessary to learn to shorthand using all its abbreviations and this would prevent its use for the didactic purposes or to aid the disabilities described above.

If anything, I have user202729/plover_run_shell: Run a shell command from Plover..

Works, but is unportable and maybe lengthy translation format.

Thanks, I'll give it a try

If anything, I have user202729/plover_run_shell: Run a shell command from Plover..

Works, but is unportable and maybe lengthy translation format.

Hi, I found the correct powershell command to play an audio file directly without running a media player. The problem now is that I don't know how to install in Plover your plugin (I use Windows 10)

It's in the plugins registry, so you should be able to install it through the plugins manager.

It's in the plugins registry, so you should be able to install it through the plugins manager.

Oh my bad! I must be blind...

Ok, tried to use the shell plugin with this command to play a wav.file of a phoneme sound:

powershell -c (New-Object Media.SoundPlayer "C:\Users\Compadmin_Asus\Music\phoneme.wav").PlaySync();

It works but it still opens the dos command window for the time the sound is played. Moreover is a bit slow: the sound comes out about one second after the stroke.

@Sillabix have you tried https://superuser.com/questions/101974/play-a-sound-maybe-wav-from-windows-line-command#comment2093832_528490 already?

Still not entirely. I have to make a few more attempts with VLC and other mediaplayer

So I tested VLC and is kinda slow and it runs in foreground so it opens briefly a window. Then, following the other suggestions in the thread, I tried with fmedia player. This is faster and can run in background. The problem is that the dos prompt window still open and close for a few milliseconds when you stroke the steno with the shell command and this is a bit annoying. With fmedia I used this command:

{PLOVER:SHELL:C:\fmedia\fmedia.exe --background sound.wav}

sol commented

At this point I’m puzzled if os.system Is responsible for that ”dos prompt “ you see.

  1. When you tried vlc, did you see a command prompt window, too?

  2. You can try the following:

Locate the file plover_run_shell.py on your system and replace the last line

	os.system(command)

with

	subprocess.Popen(command.split())

Make sure to keep the exact same indentation. I think @user202729 used tabs, so you want to indent that line by exactly one tab.

In addition add

import subprocess

just below that line containing import os.

Notes:

  • The above code should work, but I haven’t tested it.
  • This is not a proper solution, as it breaks other shell commands and does not work with paths that contain spaces for example. So use this for testing only and report back.

When you play a file with VLC using the shell plugin it opens two windows: the dos command prompt and a VLC minimized window; with fmedia instead it opens only the dos command prompt window and for a shorter time.

I tried to introduce the suggested changes to the py file but all remains quite the same: with fmedia there is still the dos prompt windows flickering for some milliseconds; with VLC two windows open (DOS command prompt and VLC) but there is also the following addiitional error which comes up after the audio file has been played:

"Python ERROR: engine_on stroke failed
FileNotFound error: {WInError 2}
Impossible to find the specified path"

I don't know If I interpreted correctly the suggested changes to the py file so I attach it below for checking purposes

'''
Execute shell command in Plover using strokes.
'''

import os
import subprocess

def shell_cmd(_: 'plover.engine.StenoEngine', command: str):
'''
Command to execute a shell command.
:param _: The Plover engine that is executing the command.
:param command: The command to execute.
'''
os.system(command)
subprocess.Popen(command.split())

sol commented

Please make two changes:

  1. Remove the line os.system(command)
  2. There is still something going wrong. Change your dictionary entry so that it uses an absolute path to the .wav file and try again. Not sure if that's the issue, but let's rule that out first.
sol commented

Actually, I'm wrong on (2). I think this error message is from Popen. It basically indicates that it can't find the fmedia.exe. I'll take a quick look.

I've pushed an update to the VLC commands plugin that could help:

  • install the plugin
  • configure access, as per the instructions
  • launch VLC, add the files you want to play to the playlist
  • use the command: {PLOVER:VLC_play:sound.wav} to play the playlist entry named sound.wav

Note: in VLC's preferences, select "All" to show all preferences, then search for "playlist", and in the "Playlist" tab, check "Play and pause", or upon finishing playing an item, VLC will automatically play the rest of the playlist.

Alternatively, you could combine the new clear and add commands to achieve the same result (only play one file).

The thing is that for the purposes described a playlist could not be used. In Eclipse I have about 20.000 wav files of each phoneme, each one associated to a dictionary entry: I suppose I couldn't set up 20.000 playlists in VLC

I don't know what the limit is for a VLC playlist is, but the API is really stupid: you have to use an ID to specify the playlist item, and it's not the ID that is shown to the user, but an internal one, which mean my plugin command implementation has to fetch the whole playlist to look for the right ID...

With that many files, I'd create a dedicated plugin.

Please make two changes:

  1. Remove the line os.system(command)
  2. There is still something going wrong. Change your dictionary entry so that it uses an absolute path to the .wav file and try again. Not sure if that's the issue, but let's rule that out first.

About 1. I removed the line os.system (command) but nothing changed, except that now VLC does not play any file anymore and it comes out just the message with the error:

"Python ERROR: engine_on stroke failed
FileNotFound error: {WInError 2}
Impossible to find the specified path"

I don't know what the limit is for a VLC playlist is, but the API is really stupid: you have to use an ID to specify the playlist item, and it's not the ID that is shown to the user, but an internal one, which mean my plugin command implementation has to fetch the whole playlist to look for the right ID...

With that many files, I'd create a dedicated plugin.

Yes, a dedicated plugin would be the best solution but I really don't know how to create it. Anyway I can try with VLC and see if it has a limit in the playlist number

Anyway the dos shell with fmedia works quite well in terms of responsiveness and speed. It would be perfect without the dos command prompt window coming out at every stroke but is already usable this way

sol commented

@Sillabix I just had the opportunity to try the solution using subprocess.Popen on a Windows box and this works perfectly for me.

It will not show the command prompt window. So from what I understand this could be turned into exactly what you want.

I'm not sure what went wrong on your computer. The error message indicates that it could not find the executable. Are you sure that there weren't any spaces in the path?

sol commented

@Sillabix I'm not sure how important this is to you, but this is a small thing. Here is a fully tested solution.

  1. Put this into plover_run_shell.py:
    import subprocess
    def shell_cmd(_, file):
        subprocess.Popen(["c:\\fmedia\\fmedia.exe", "--background", file])
  2. Restart Plover!
  3. Change your dictionary entry to something like {PLOVER:SHELL:c:\path\to\sound.wav}. Use an absolute path to your wave files, at least for a start.

If this works for you and you are gonna use this then you would want to package this up as a new plugin.

@Sillabix I'm not sure how important this is to you, but this is a small thing. Here is a fully tested solution.

  1. Put this into plover_run_shell.py:
    import subprocess
    def shell_cmd(_, file):
        subprocess.Popen(["c:\\fmedia\\fmedia.exe", "--background", file])
  2. Restart Plover!
  3. Change your dictionary entry to something like {PLOVER:SHELL:c:\path\to\sound.wav}. Use an absolute path to your wave files, at least for a start.

If this works for you and you are gonna use this then you would want to package this up as a new plugin.

Thanks a lot! At the moment I'm traveling so I can't give it a try. I'll let you know ASAP

Sorry for reopening this issue after so long time. I finally tried the last suggestion by sol and now the plover_run_shell.py appears the following

'''
Execute shell command in Plover using strokes.
'''

import os

import subprocess
def shell_cmd(_, file):
subprocess.Popen(["c:\fmedia\fmedia.exe", "--background", file])

When I try to play a file with the following steno definition:

{PLOVER:SHELL:C:\Users\Compadmin_Asus\Music\test.wav}

The file is not played and appears the message:
Plover
ERROR:engine on_stroked failed
FileNotFoundError: [WinError 2]
Impossible to find the specified file