Remote Ham Radio through a Browser via a Raspberry Pi

The Experiment: In this experiment were re-visiting a Browser based  Ham Radio  Remote Client. The Browser Audio will be processed through the Web Audio API. A Raspberry Pi 2/3 Node.js Server will process the  CAT commands and Stream the Speaker/Microphone Audio to and from the Browser Ham Radio  Remote Client.

The hybrid Android App will display the Browser Ham Remote  Radio  Client in a  Webview .  The PTT button in the Webview will toggle the JAVA Speaker/Microphone Audio stream.

Note:  Switching to the Web Audio API, because the latency on the HTML5 <audio> element is just to high.

Table of Contents
1. Progress
2. Software/npm Packages
3. Directory structure
4. Hardware
5. Notes
6. Conclusion
7. Reference Links

Other Ham Radio Remote Experiments on this site
1. Remote Ham Radio WebRTC Audio via a Raspberry Pi
2. Remote Ham Radio HTML5 Audio via a Raspberry Pi
3. Raspberry Pi Ham Radio Remote Base via Web Audio API  <- You are here
4. Remote Ham Radio Control via Yaesu PCC / Raspberry Pi
3. Remote Ham Radio Yaesu PCC Software Parole Audio via a Raspberry Pi
6. Remote Hame Radio JAVA Audio a Complete Solution via a Raspberry Pi


Been working on this for the last three weeks, had to solve a lot of issues but finally have them resolved. Now have a working browser based Ham Radio Remote Client using the Web Audio API for the Microphone/Speaker Audio stream. The  Raspberry Pi will process  the Microphone/Speaker Audio Stream and Transceiver CAT commands.

Note:  Still working on a Web Audio API socket.iostream audio player, but for right now have integrated a really good low latency Web Audio API player found here. The PTT button toggles the 3LAS Player Mute/Un-mute button. This issue has now been resolved

To access the remote Transceiver just launch a Browser enter the URL and Login. In the remote client, click Connect one’s connected the Connect button label will change to Power Off and the Transceiver Audio will be heard though the PC speaker. To Transmit hold down right mouse button on the PTT button, the PTT button will turn RED then speak into the Microphone, when you let go of the right mouse button TX will return to RX and the Transceiver Audio again will be heard though the speaker.

To change the frequency: Click/touch the frequency digest then click/touch dial Up/Down button that will increase/decease the frequency digit selected. The other controls are self explanatory, click/touch any off the buttons to change that option. The PTT click/touch on touch or right mouse button down TX on release will return to RX

The Browser  Client is that easy to use, same procedure on the hybrid Android App.

Tested the Browser Ham Radio Remote Client on Linux through  Chrome. The Audio player worked, but was unable to test Microphone Audio since google has blocked Microphone access from none HTTPS links, all the other functions worked fine. Usually don’t use Chrome but that was the default browser on th Linux image.

Note: Click for Browser and Touch for Android App.

In the Hybrid Android App the Mic Gain has been removed, since were using a JAVA Audio stream.

Tested PTT in the Hybrid Android App, PTT in Webview  will toggles the JAVA Microphone/Speaker Audio stream, and the RX element will toggle to TX then Back to RX.

Note: For security reason: Google Chrome will block Microphone access from none “HTTPS” web links, on  the Hybrid Android App, I am using a JAVA Microphone/Speaker Audio stream.

Integrated the real Android Ham Radio Remote App through the  Yaesu Ham Radio Remote Server. Now can access the  radio  through the Browser   Ham Radio Remote Client,  the Hybrid Android Ham Radio Remote Client and  real Android  Ham Radio  Remote Client.

4/2/2018: Fabricated the small enclosure for the Audio interface which goes between the USB Audio card / Radio. Using on ICOM’s  CIV and ACC1  has everything needed AF detector output, Modulator input and  PTT send. There is a simple High Pass filter between the AF detector output and the USB Microphone input. This help filter out some of the background noise/hiss.

Using ACC1: So that  the radio can be used in  the shack without having to worry about changing any of the remote base Audio settings.

4/17/2018: Well did not think it was possible but after 5 (five) weeks of trying different Web Audio API configuration, finally have a Browser based Socket-io low latency Audio player. Still not perfect and it is resource intensive, but it is possible to get low latency Audio though a Browser. Tested HTTPS Remote Ham Radio Server through Firefox, Chrome Microphone / Speaker Audio does work, also the HTTPS Remote Ham Radio Server only uses 1 (one) TCP-IP port for HTTPS – Microphone – Speaker – CAT Radio Control server. Tested low latency Web Audio API Player on Android phone worked but phone does not have enough CPU power, will continue to use JAVA Microphone / Speaker Audio on Android phone.

Rev 7.2.2 Raspberry Pi Ham Radio Remote Controller.
1. Save On/Off power switch
2. Select-able RS232 / CIV Inputs
3. PTT Led / Relay
4. ICOM On/Off Relay Output

Now have it working on Windows PC ,  Linux,  Hybrid Android App and real Android App. Currently running two Raspberry Pi 3 Remote Ham Radio server  1. ICOM  2. YAESU. Can now access either Transceiver from anywhere through Phone or PC.



  1. 2017-11-29-raspbian-stretch-lite.img
  2. Node.js
  3. NPM

NPM Dependencies:

  1. http
  2. express
  3. express-device
  4. serialport
  6. binaryjs
  7. onoff
  8. onoff
  9. ws


Directory structure:




  1. Raspberry Pi
  2. USB Sound Card
  3. Micro USB 5V AC Adapters
  4. Serial Level Converter here
  5. Another Audio Interface here here



The biggest issue when using HTML5 Audio has been high audio latency, direct Web Audio API Speaker/Microphone access works best for low latency audio. Either way the Audio stream still has some crackle from overflow.

To eliminate some of the radio static use the RF Gain control.

Have a work around for ICOM band switching, create a band stacking register with in the browser based Ham Radio Remote Client.

Web Audio API:
Now have Audio player streaming live Microphone audio over Socket-io, Socket-io-Stream, Binary.js. Socket-io-Stream works but not very stable stream will un-sink and become choppy.
1. Binary.js – streams hex string –
stream.write(data.toString(‘hex’)) -> dataToNumberArr(data)

2. Socket-io – streams hex string –
socket.emit(‘stream’, data.toString(‘hex’)) -> dataToNumberArr(data)

3. Socket-io-Stream – streams Uint8array –
stream.write(data.toString(‘hex’)) -> dataToNumberArr(data.toString())

Muting the Player Audio stream is usually done by setting the  GainNode to zero(0), but as usual could not get that to work. So  a work around stop the source from playing PTT = 0 Play audio PTT = 1 Mute audio

1. if (PTT == 0)  source.start(nextTime);

Now using to Mute Audio

1. source.start(nextTime);
if (PTT == 1) source.stop(0);

The audio latency slowly increases as time goes by, to keep the latency low, reset the socket to the audio server every 5 minutes, it causes a quick click which just blends in with the background static.  PTT Down the time is stopped, PTT Up the time is restarted.

1. window.binaryServerspk.close();

Discovered  that low latency Audio will not play very well on older portable PC. On Windows 7 64bit PC was able to bring the CPU usage down to 3-6%. When played on a older Vista PC 50-67% it does play but will lockup browser.

The HTTPS Ham Radio Remote Server / Client is working really well. It only requires one(1) TCP/IP Address and Two(2) Ports. HTTP is automatically routed to HTTPS.Things are working so well  added a video stream to display the band scope.

Have improved the video stream and added a Video On/Off button which will show hide the video display.

Things are getting better now using socket-io for CAT control, Server Microphone stream  to PC Speaker, Video stream to browser, then using  socket-io-stream to stream PC Microphone to Server Speaker.  Much less code and only 1(one) Websocket between Server and Browser. Inserted Band pass Filter into the Speaker / Microphone stream, much cleaner audio with filter installed. Finally found a good way to link all the filter to the destination.

audioInput = context.createMediaStreamSource(e)
source = context.createBufferSource();

Fine tuned the low latency Audio Player to the were it will play on and old Vista Portable, play’s great on Win7 PC. Now need to update the Android App.

Thing are working so well decided to make a nicer desktop Ham Radio Remote Client, on Android will keep the same client.

Keep adding feature video popup can be moved anywhere on the screen…

Added a lot of new features, Audio Band pass / notch filter controls very useful to remove the background noise – static. Inserted a Dynamics Compressor into the Microphone Audio stream this really improves the Mic Audio. Also Auto IDer which automatically ID’s every 8 minutes during a QSO and will automatically reset after a 15 minute pause.

Testing Different Recorders on the Raspberry Pi Server:
Raspberry Pi Microphone Audio CPU usage:
1. FFMPEG         CPU usage 17%
2. ARECORD      CPU usage 0.7 – 1%.
Raspberry Pi Video CPU usage:
1. FSWEBCAM   CPU usage 0.3%

Switched to  the Server Microphone Audio Stream to ARECORD.
Total CPU usage with Speaker/Microphone and Video On  31-37%.

Been doing a lot of fine tuning to get Web Audio API working on older Laptops running Win Vista – XP. Had to make a compromise which effected the audio latency. To get sub second Audio had  Arecord buffer set to 5ms worked great on Win7 64bit, but would freeze Win Vista –  XP older Laptop.  Now have Buffer set to 1000ms which fixed the Win Vista –  XP older Laptop problem but increased the Audio latency.

Raspberry Pi Server Speaker/Microphone with Video On CPU usage  = 6-7% was 31-37%
Raspberry Pi ARECORD CPU usage =   0.3%.
Raspberry Pi FSWEBCAM CPU usage  =  0.3%

Win7 64bit Firefox CPU = 0-2%
Win Vista Firefox CPU = 0-50%
Win XP Firefox  CPU =  0-50%
Linux = Chrome Working OK

Big Improvement on CPU usage and now older Laptops are no longer freezing up…

Have been using the Ham Radio Remote Client every day and all working as expected.

Read that WebRTC had the best Audio latency: Well I did some WebRTC testing and discovered that it has about a one(1) second delay, I can get a one(1) second audio delay using the <audio> element.  Also felt that the WebRTC audio quality was poor.

Possibility: To turn the ICOM Transceiver ON/Off, installed an ON/Off Relay between the Power Supply and the Transceiver , Power Supply always On, Transceiver always On but then turn off by the Relay. When Connect button is click/touched it  start a 10 second time and which wait’s for the Transceiver to boot-up, after 10 seconds a request is made for the radio ID, if the Transceiver is On it will replay back the Transceiver ID and turn the connect button label will change to Power On. If Transceiver is of or used by anther the button label well return back to Connect. One other nice thing, if the Web Client loses the connection to the server the Transceiver will automatically be turned Off.

Now considering: Using a servo to turn the radio Off/On…

Settled on: After look at  the ICOM 756PROII service manual decided to put a Transistor across the On/Off switch which will wire that to the two un-used pin on the power plug that will then go to the Raspberry Pi Ham Radio Remote controller. Nice clean Mod.


It’s a lot easier to remote a Yaesu/Kenwood/Elecraft transceiver, ICOM civ commands are difficult to use and older radios have no On/OFF radio command. Will code a second version for Yeasu FT950/FT2000 Ham Radio Remote.


It is totally possible to develop a Low Latency browser based Ham Radio Remote Client using the Web Audio API , via a Raspberry Pi 2/3.

Note: It does take a late model PC to process the Web Audio API Low  Latency Audio stream,  it will work on older PC but CPU usage quickly goes to 100% freezing all processing.

Note: Unless accesses is given to the HTML5 <audio> tag buffer  it will be hard to get low latency audio through the HTML5 <audio> tag.


Reference Links:

1. Web-Audio-Stream
2. FFMPEG StreamingGuide
3. Experiments with WebAudio
4. Proper way to play data chunks
5. Transferring Sound Data with Binary.JS
6 3LAS (Low Latency Live Audio Streaming)
7. Choppy/inaudible playback with chunked
8. Web Audio playing back in Chrome but not Firefox
9. Web Audio API
10. Node.js
11. npm