v1.0
This commit is contained in:
parent
eb91e1f684
commit
a0416f3661
43
README.md
43
README.md
@ -6,20 +6,41 @@ LogStreamer est un logiciel permettant la diffusion sonore d'un fichier via un s
|
|||||||
## Prérequis
|
## Prérequis
|
||||||
|
|
||||||
* python3
|
* python3
|
||||||
* pigtail
|
* oggenc
|
||||||
```
|
|
||||||
pip3 install pigtail
|
|
||||||
```
|
|
||||||
|
|
||||||
## Utilisation
|
## Utilisation
|
||||||
|
|
||||||
* Ajuster les valeurs des constantes LOG et WAV_OUTPUT en fonction des besoins
|
```
|
||||||
* LOG: Le log à jouer
|
logstreamer.py -h
|
||||||
* WAV_OUTPUT: Le fichier wav de sortie
|
|
||||||
* MAX_DURATION: La durée maximale d'une note
|
usage: logstreamer.py [-h] --log LOG [--workdir WORKDIR] [--duration DURATION]
|
||||||
* EXCLUDE: Les caractères dont les valeurs sont ajoutées à cette liste ne seront pas traités
|
[--amplitude AMPLITUDE] [--framerate FRAMERATE]
|
||||||
* Exécuter ```python3 logstreamer.py```
|
[--adjust ADJUST ADJUST]
|
||||||
* Lire le fichier wav résultant avec un lecteur audio supportant le format wav
|
[--exclude [EXCLUDE [EXCLUDE ...]]] --host HOST --port
|
||||||
|
PORT --user USER --password PASSWORD --mount MOUNT
|
||||||
|
[--protocol PROTOCOL]
|
||||||
|
|
||||||
|
optional arguments:
|
||||||
|
-h, --help show this help message and exit
|
||||||
|
--log LOG Le fichier de log à traiter (requis)
|
||||||
|
--workdir WORKDIR Le répertoire de travail (défaut: /tmp)
|
||||||
|
--duration DURATION La durée d'une note (défaut: 0.008)
|
||||||
|
--amplitude AMPLITUDE
|
||||||
|
Le niveau sonore (défaut: 0.5)
|
||||||
|
--framerate FRAMERATE
|
||||||
|
Le taux d'échantillonage (défaut: 44100)
|
||||||
|
--adjust ADJUST ADJUST
|
||||||
|
Facteurs d'ajustement (défaut: 5000 20000)
|
||||||
|
--exclude [EXCLUDE [EXCLUDE ...]]
|
||||||
|
Liste des caractères non traités (défaut: [])
|
||||||
|
--host HOST Server Icecast2 (requis)
|
||||||
|
--port PORT Port TCP sur lequel contacter le serveur Icecast2
|
||||||
|
(requis)
|
||||||
|
--user USER Nom d'utilisateur (requis)
|
||||||
|
--password PASSWORD Mot de passe (requis)
|
||||||
|
--mount MOUNT Point de montage Icecast2 (requis)
|
||||||
|
--protocol PROTOCOL Protocol à utiliser (défaut: http)
|
||||||
|
```
|
||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
|
106
logstreamer.py
106
logstreamer.py
@ -1,35 +1,13 @@
|
|||||||
#!/bin/env python3
|
#!/bin/env python3
|
||||||
|
|
||||||
"""
|
import os
|
||||||
# Prérequis
|
|
||||||
|
|
||||||
* python3
|
|
||||||
* pigtail
|
|
||||||
```
|
|
||||||
pip3 install pigtail
|
|
||||||
```
|
|
||||||
|
|
||||||
# Utilisation
|
|
||||||
|
|
||||||
* Ajuster les valeurs des constantes LOG et WAV_OUTPUT en fonction des besoins
|
|
||||||
* LOG: Le log à jouer
|
|
||||||
* WAV_OUTPUT: Le fichier wav de sortie
|
|
||||||
* MAX_DURATION: La durée maximale d'une note
|
|
||||||
* EXCLUDE: Les caractères dont les valeurs sont ajoutées à cette liste ne seront pas traités
|
|
||||||
* Exécuter python3 text2wav.py
|
|
||||||
* Lire le fichier wav résultant avec un lecteur audio supportant le format wav
|
|
||||||
|
|
||||||
"""
|
|
||||||
import wave
|
import wave
|
||||||
import math
|
import math
|
||||||
|
import shout
|
||||||
import struct
|
import struct
|
||||||
import random
|
import random
|
||||||
from pygtail import Pygtail
|
import argparse
|
||||||
|
import subprocess
|
||||||
LOG = '/var/log/httpd/access_log'
|
|
||||||
WAV_OUTPUT = '/home/doug/test/test.wav'
|
|
||||||
MAX_DURATION = 0.08
|
|
||||||
EXCLUDE = []
|
|
||||||
|
|
||||||
def sine_wave(frequency=444, framerate=44100, amplitude=0.5, duration=1):
|
def sine_wave(frequency=444, framerate=44100, amplitude=0.5, duration=1):
|
||||||
"""
|
"""
|
||||||
@ -51,25 +29,85 @@ def sine_wave(frequency=444, framerate=44100, amplitude=0.5, duration=1):
|
|||||||
return struct.pack('<{}h'.format(len(data)), *data)
|
return struct.pack('<{}h'.format(len(data)), *data)
|
||||||
|
|
||||||
def notes_table(oord):
|
def notes_table(oord):
|
||||||
freq = math.floor(math.log(oord)*5000-20000)
|
freq = math.fabs(math.floor(math.log(oord)*int(args.adjust[0])-int(args.adjust[1])))
|
||||||
duration = MAX_DURATION
|
duration = args.duration
|
||||||
return (freq, duration)
|
return (freq, duration)
|
||||||
|
|
||||||
with wave.open(WAV_OUTPUT, 'wb') as wave_file:
|
def convert2ogg(wav_file, ogg_file):
|
||||||
|
result = subprocess.call(['oggenc', wav_file, '-o {} --utf8 -t {}'.format(ogg_file, args.log)])
|
||||||
|
return result
|
||||||
|
|
||||||
|
def push_ogg(ogg_file):
|
||||||
|
icecast = shout.Shout()
|
||||||
|
icecast.host = args.host
|
||||||
|
icecast.port = args.port
|
||||||
|
icecast.user = args.user
|
||||||
|
icecast.password = args.password
|
||||||
|
icecast.mount = args.mount
|
||||||
|
icecast.protocol = args.protocol
|
||||||
|
icecast.format = 'ogg'
|
||||||
|
print("Connecting to {}://{}:{}/{}".format(args.protocol, args.host, args.port, args.mount))
|
||||||
|
icecast.open()
|
||||||
|
with open(ogg_file, 'rb') as ogg:
|
||||||
|
total = 0
|
||||||
|
print("- Reading 4096 bytes")
|
||||||
|
new_buff = ogg.read(4096)
|
||||||
|
while True:
|
||||||
|
cur_buff = new_buff
|
||||||
|
print("- Reading next 4096 bytes")
|
||||||
|
new_buff = ogg.read(4096)
|
||||||
|
total += len(cur_buff)
|
||||||
|
if len(cur_buff) == 0:
|
||||||
|
print(" - Buffer is empty: EOF")
|
||||||
|
print(" - Sent: {} bytes".format(total))
|
||||||
|
break
|
||||||
|
print("- Sending 4096 bytes")
|
||||||
|
icecast.send(cur_buff)
|
||||||
|
icecast.sync()
|
||||||
|
|
||||||
|
def main():
|
||||||
|
wav_output = "{}.wav".format(os.path.basename(args.log).split('.')[0])
|
||||||
|
wav_output = os.path.join(args.workdir, wav_output)
|
||||||
|
ogg_output = "{}.ogg".format(os.path.basename(args.log).split('.')[0])
|
||||||
|
ogg_output = os.path.join(args.workdir, ogg_output)
|
||||||
|
|
||||||
|
with wave.open(wav_output, 'wb') as wave_file:
|
||||||
nchannels = 1
|
nchannels = 1
|
||||||
sampwidth = 2
|
sampwidth = 2
|
||||||
framerate = 44100
|
framerate = args.framerate
|
||||||
wave_file.setnchannels(nchannels)
|
wave_file.setnchannels(nchannels)
|
||||||
wave_file.setsampwidth(sampwidth)
|
wave_file.setsampwidth(sampwidth)
|
||||||
wave_file.setframerate(framerate)
|
wave_file.setframerate(framerate)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
for line in Pygtail(LOG):
|
with open(args.log, 'r') as log:
|
||||||
for letter in line:
|
for letter in log.read():
|
||||||
oord = ord(letter)
|
oord = ord(letter)
|
||||||
freq, duration = notes_table(oord)
|
freq, duration = notes_table(oord)
|
||||||
if oord not in EXCLUDE:
|
if oord not in args.exclude:
|
||||||
print("Caractère: {} | Ord: {} | Fréquence: {} | Durée: {}".format(letter, oord, freq, duration))
|
print("Caractère: {} | Ord: {} | Fréquence: {} | Durée: {}".format(letter, oord, freq, duration))
|
||||||
wave_file.writeframes(sine_wave(frequency=freq, duration=duration))
|
wave_file.writeframes(sine_wave(frequency=freq, duration=duration))
|
||||||
|
result = convert2ogg(wav_output, ogg_output)
|
||||||
|
if result == 0:
|
||||||
|
push_ogg(ogg_output)
|
||||||
|
else:
|
||||||
|
raise Exception("Erreur lors de la conversion en OGG: {}".format(result))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print('\033[91m{}\033[0m'.format(e))
|
print('\033[91m{}\033[0m'.format(e))
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument('--log', help='Le fichier de log à traiter (requis)', type=str, required=True)
|
||||||
|
parser.add_argument('--workdir', help='Le répertoire de travail (défaut: /tmp)', type=str, default='/tmp')
|
||||||
|
parser.add_argument('--duration', help="La durée d'une note (défaut: 0.008)", type=float, default=0.08)
|
||||||
|
parser.add_argument('--amplitude', help="Le niveau sonore (défaut: 0.5)", type=float, default=0.5)
|
||||||
|
parser.add_argument('--framerate', help="Le taux d'échantillonage (défaut: 44100)", type=int, default=44100)
|
||||||
|
parser.add_argument('--adjust', help="Facteurs d'ajustement (défaut: 5000 20000)", nargs=2, default=[5000, 20000])
|
||||||
|
parser.add_argument('--exclude', help="Liste des caractères non traités (défaut: [])", nargs="*", default=[])
|
||||||
|
parser.add_argument('--host', help="Server Icecast2 (requis)", type=str, required=True)
|
||||||
|
parser.add_argument('--port', help="Port TCP sur lequel contacter le serveur Icecast2 (requis)", type=int, required=True)
|
||||||
|
parser.add_argument('--user', help="Nom d'utilisateur (requis)", type=str, required=True)
|
||||||
|
parser.add_argument('--password', help="Mot de passe (requis)", type=str, required=True)
|
||||||
|
parser.add_argument('--mount', help="Point de montage Icecast2 (requis)", type=str, required=True)
|
||||||
|
parser.add_argument('--protocol', help="Protocol à utiliser (défaut: http)", type=str, default='http')
|
||||||
|
args = parser.parse_args()
|
||||||
|
main()
|
||||||
|
Loading…
Reference in New Issue
Block a user