Compare commits
4 Commits
84ef307ab5
...
0b8763b30e
Author | SHA1 | Date |
---|---|---|
Fierelier | 0b8763b30e | |
Fierelier | a91ab70f57 | |
Fierelier | e4f0ad050e | |
Fierelier | fa3e88082c |
19
README.md
19
README.md
|
@ -14,15 +14,22 @@ Audio I/O for real-time applications, like VoIP.
|
|||
- `aspew-in.py` takes a microphone as an input, and outputs it to pipe.
|
||||
- `aspew-out.py` takes input from a pipe, and outputs it to a speaker.
|
||||
|
||||
## Flags
|
||||
Flags formatted as `-s` or `--long`.
|
||||
|
||||
### in & out:
|
||||
- `-l`: List devices as JSON
|
||||
- `-h`: Use human-readable format
|
||||
|
||||
## Arguments
|
||||
Arguments are pairs of key=value.
|
||||
|
||||
### in & out:
|
||||
- `device`: The device, a number (Default: Your default audio device.)
|
||||
- `device`: The device, a number (Default: `-1` aka. your default device)
|
||||
- `format`: The encoding of your audio, choices: [https://people.csail.mit.edu/hubert/pyaudio/docs/#pasampleformat](https://people.csail.mit.edu/hubert/pyaudio/docs/#pasampleformat) (Default: `paUInt8`)
|
||||
- `channels`: How many channels the audio has (Default: `1`)
|
||||
- `bitrate`: How high the refresh rate of the audio is in Hz (Default: `8000`)
|
||||
- `buffersize`: The buffer-size, in seconds. Higher buffer-sizes reduce CPU load and risk of stutter, but raise delay (Default: `0.05`)
|
||||
- `buffersize`: The buffer-size, in seconds. Higher buffer-sizes reduce CPU load and risk of stutter, but raise delay. Raise this if you get constant stutter (Default: `0.05`)
|
||||
|
||||
### out-only:
|
||||
- `store`: How much audio to store in the back-buffer at maximum before cutting it off, in seconds. Raise this if you get inconsistent playback (Default: `0.3`)
|
||||
|
@ -32,4 +39,10 @@ Arguments are pairs of key=value.
|
|||
Listen to your default microphone at default settings.
|
||||
|
||||
- `./aspew-in.py format=paInt16 bitrate=48000 channels=2 | ./aspew-out.py format=paInt16 bitrate=48000 channels=2`
|
||||
Listen to your default microphone at 16-bit, 48000Hz, stereo.
|
||||
Listen to your default microphone at 16-bit, 48000Hz, stereo.
|
||||
|
||||
- `./aspew-in.py -lh`
|
||||
List your input devices.
|
||||
|
||||
- `./aspew-out.py -lh`
|
||||
List your output devices.
|
48
aspew-in.py
48
aspew-in.py
|
@ -5,6 +5,25 @@ import time
|
|||
import pyaudio
|
||||
unbufferedStdout = os.fdopen(sys.stdout.fileno(),"wb",0) # Make unbuffered stdout
|
||||
|
||||
def parseFlags():
|
||||
rtn = []
|
||||
for arg in sys.argv[1:]:
|
||||
arg = arg.replace(" ","")
|
||||
arg = arg.replace("\t","")
|
||||
arg = arg.replace("\r","")
|
||||
arg = arg.replace("\n","")
|
||||
if arg[0] != "-": continue
|
||||
if arg == "-": continue
|
||||
|
||||
if arg[:2] == "--":
|
||||
rtn.append(arg[2:])
|
||||
continue
|
||||
|
||||
for i in arg[1:]:
|
||||
rtn.append(i)
|
||||
|
||||
return rtn
|
||||
|
||||
def parseSettings():
|
||||
rtn = {}
|
||||
for arg in sys.argv[1:]:
|
||||
|
@ -25,12 +44,41 @@ def streamHandler(in_data, frame_count, time_info, status):
|
|||
unbufferedStdout.write(in_data)
|
||||
return (in_data, pyaudio.paContinue)
|
||||
|
||||
flags = parseFlags()
|
||||
|
||||
if "l" in flags:
|
||||
devices = {}
|
||||
audio = pyaudio.PyAudio()
|
||||
defaultDevice = audio.get_default_host_api_info()["defaultInputDevice"]
|
||||
devices["default"] = defaultDevice
|
||||
for i in range(0, audio.get_device_count()):
|
||||
info = audio.get_device_info_by_index(i)
|
||||
if info["maxInputChannels"] == 0: continue
|
||||
|
||||
devices[i] = {
|
||||
"name": info["name"],
|
||||
"api": audio.get_host_api_info_by_index(info["hostApi"])["name"]
|
||||
}
|
||||
|
||||
if not "h" in flags:
|
||||
import json
|
||||
print(json.dumps(devices))
|
||||
else:
|
||||
print("\nAvailable input devices:")
|
||||
for i in devices:
|
||||
if i == "default": continue
|
||||
st = str(i)+ ": " +devices[i]["name"]+ " [" +devices[i]["api"]+ "]"
|
||||
if i == defaultDevice: st = st + " *"
|
||||
print(st)
|
||||
sys.exit(0)
|
||||
|
||||
settings = parseSettings()
|
||||
audioFormat = getSetting(settings,str,["f","format"],"paUInt8")
|
||||
audioChannels = getSetting(settings,int,["c","channel","channels"],1)
|
||||
audioRate = getSetting(settings,int,["r","rate","bitrate"],8000)
|
||||
audioBuffer = getSetting(settings,float,["b","buffer","buffersize"],0.05)
|
||||
audioDevice = getSetting(settings,int,["d","device"],None)
|
||||
if audioDevice == -1: audioDevice = None
|
||||
|
||||
audioFormat = getattr(pyaudio,audioFormat)
|
||||
audioBuffer = round(audioRate * audioBuffer)
|
||||
|
|
50
aspew-out.py
50
aspew-out.py
|
@ -58,6 +58,25 @@ def streamHandler(in_data, frame_count, time_info, status):
|
|||
data += getAudioFrame()
|
||||
return (data, pyaudio.paContinue)
|
||||
|
||||
def parseFlags():
|
||||
rtn = []
|
||||
for arg in sys.argv[1:]:
|
||||
arg = arg.replace(" ","")
|
||||
arg = arg.replace("\t","")
|
||||
arg = arg.replace("\r","")
|
||||
arg = arg.replace("\n","")
|
||||
if arg[0] != "-": continue
|
||||
if arg == "-": continue
|
||||
|
||||
if arg[:2] == "--":
|
||||
rtn.append(arg[2:])
|
||||
continue
|
||||
|
||||
for i in arg[1:]:
|
||||
rtn.append(i)
|
||||
|
||||
return rtn
|
||||
|
||||
def parseSettings():
|
||||
rtn = {}
|
||||
for arg in sys.argv[1:]:
|
||||
|
@ -74,12 +93,42 @@ def getSetting(lst,tp,keys,default = None):
|
|||
return tp(lst[key])
|
||||
return default
|
||||
|
||||
flags = parseFlags()
|
||||
|
||||
if "l" in flags:
|
||||
devices = {}
|
||||
audio = pyaudio.PyAudio()
|
||||
defaultDevice = audio.get_default_host_api_info()["defaultOutputDevice"]
|
||||
devices["default"] = defaultDevice
|
||||
for i in range(0, audio.get_device_count()):
|
||||
info = audio.get_device_info_by_index(i)
|
||||
if info["maxOutputChannels"] == 0: continue
|
||||
|
||||
devices[i] = {
|
||||
"name": info["name"],
|
||||
"api": audio.get_host_api_info_by_index(info["hostApi"])["name"]
|
||||
}
|
||||
|
||||
if not "h" in flags:
|
||||
import json
|
||||
print(json.dumps(devices))
|
||||
else:
|
||||
print("\nAvailable output devices:")
|
||||
for i in devices:
|
||||
if i == "default": continue
|
||||
st = str(i)+ ": " +devices[i]["name"]+ " [" +devices[i]["api"]+ "]"
|
||||
if i == defaultDevice: st = st + " *"
|
||||
print(st)
|
||||
sys.exit(0)
|
||||
|
||||
settings = parseSettings()
|
||||
audioFormat = getSetting(settings,str,["f","format"],"paUInt8")
|
||||
audioChannels = getSetting(settings,int,["c","channel","channels"],1)
|
||||
audioRate = getSetting(settings,int,["r","rate","bitrate"],8000)
|
||||
audioBuffer = getSetting(settings,float,["b","buffer","buffersize"],0.05)
|
||||
audioStore = getSetting(settings,float,["s","store"],0.3)
|
||||
audioDevice = getSetting(settings,int,["d","device"],None)
|
||||
if audioDevice == -1: audioDevice = None
|
||||
|
||||
letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
audioBitrate = audioFormat
|
||||
|
@ -94,6 +143,7 @@ lastFrame = bytearray(int(audioFrameSize))
|
|||
|
||||
kwargs = {
|
||||
"output": True,
|
||||
"output_device_index": audioDevice,
|
||||
"format": audioFormat,
|
||||
"channels": audioChannels,
|
||||
"frames_per_buffer": audioBuffer,
|
||||
|
|
Loading…
Reference in New Issue