mirror of
https://github.com/damp11113/xHE-Opus.git
synced 2025-04-27 22:48:08 +00:00
v3
This commit is contained in:
parent
a6ef8f580f
commit
2bd1a050ab
62
encode.py
62
encode.py
@ -1,19 +1,61 @@
|
|||||||
from libxheopus import DualOpusEncoder, XopusWriter
|
from libxheopus import DualOpusEncoder, XopusWriter
|
||||||
import wave
|
import wave
|
||||||
|
import argparse
|
||||||
|
from tqdm import tqdm
|
||||||
|
|
||||||
encoder = DualOpusEncoder("restricted_lowdelay", version="hev2")
|
parser = argparse.ArgumentParser(description='xHE-Opus Encoder')
|
||||||
encoder.set_bitrates(12000)
|
|
||||||
encoder.set_bitrate_mode("CVBR")
|
|
||||||
desired_frame_size = encoder.set_frame_size(120)
|
|
||||||
|
|
||||||
wav_file = wave.open(r"test.wav", 'rb')
|
parser.add_argument("input", help='Input wav int16 file path')
|
||||||
|
parser.add_argument("output", help='Output xopus file path')
|
||||||
|
parser.add_argument('-sr', "--samprate", help='Set samples rates', default=48000, type=int)
|
||||||
|
parser.add_argument('-b', '--bitrate', help='Set Bitrate (bps)', default=64000, type=int)
|
||||||
|
parser.add_argument('-c', '--compress', help='Set compression: 0-10', default=10, type=int)
|
||||||
|
parser.add_argument('-l', '--loss', help='Set packet loss: 0-100%', default=0, type=int)
|
||||||
|
parser.add_argument('-fs', '--framesize', help='Set frame size: 120, 100, 80, 60, 40, 20, 10 or 5', default=120, type=int)
|
||||||
|
parser.add_argument('-bm', '--bitmode', help='Set Bitrate mode: CBR VBR CVBR', default="CVBR")
|
||||||
|
parser.add_argument('-bw', '--bandwidth', help='Set bandwidth: auto, fullband, superwideband, wideband, mediumband or narrowband', default="fullband")
|
||||||
|
parser.add_argument('-a', '--app', help='Set bandwidth: restricted_lowdelay, audio, voip', default="restricted_lowdelay")
|
||||||
|
parser.add_argument('-v', '--ver', help='Set opus version: hev2 (enable 120, 100, 80 framesize), he, exper, stable, old', default="hev2")
|
||||||
|
parser.add_argument('-pred', '--prediction', help='Enable prediction', action='store_true', default=False)
|
||||||
|
parser.add_argument('-ph', '--phaseinvert', help='Enable phase invert', action='store_true', default=False)
|
||||||
|
parser.add_argument('-dtx', help='Enable discontinuous transmission', action='store_true', default=False)
|
||||||
|
parser.add_argument('-sb', "--samebitrate", help='Enable same bitrate (bitrate x2)', action='store_true', default=False)
|
||||||
|
|
||||||
file = r"test.xopus"
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
progress = tqdm()
|
||||||
|
|
||||||
|
progress.desc = "creating encoder..."
|
||||||
|
encoder = DualOpusEncoder(args.app, args.samprate, args.ver)
|
||||||
|
encoder.set_bitrates(args.bitrate, args.samebitrate)
|
||||||
|
encoder.set_bitrate_mode(args.bitmode)
|
||||||
|
encoder.set_bandwidth(args.bandwidth)
|
||||||
|
encoder.set_compression(args.compress)
|
||||||
|
encoder.set_packet_loss(args.loss)
|
||||||
|
encoder.set_feature(args.prediction, args.phaseinvert, args.dtx)
|
||||||
|
desired_frame_size = encoder.set_frame_size(args.framesize)
|
||||||
|
|
||||||
|
xopus = XopusWriter(args.output, encoder)
|
||||||
|
|
||||||
|
allframe = 0
|
||||||
|
|
||||||
|
progress.desc = "reading wav file..."
|
||||||
|
wav_file = wave.open(args.input, 'rb')
|
||||||
|
|
||||||
|
while True:
|
||||||
|
frames = wav_file.readframes(desired_frame_size)
|
||||||
|
|
||||||
|
if not frames:
|
||||||
|
break # Break the loop when all frames have been read
|
||||||
|
|
||||||
|
allframe += len(frames)
|
||||||
|
|
||||||
|
progress.total = allframe
|
||||||
|
wav_file.rewind()
|
||||||
|
|
||||||
xopus = XopusWriter(file, encoder)
|
|
||||||
|
|
||||||
# Read and process the WAV file in chunks
|
# Read and process the WAV file in chunks
|
||||||
print("encoding...")
|
progress.desc = "encoding..."
|
||||||
while True:
|
while True:
|
||||||
frames = wav_file.readframes(desired_frame_size)
|
frames = wav_file.readframes(desired_frame_size)
|
||||||
|
|
||||||
@ -22,5 +64,7 @@ while True:
|
|||||||
|
|
||||||
xopus.write(frames)
|
xopus.write(frames)
|
||||||
|
|
||||||
|
progress.update(len(frames))
|
||||||
|
|
||||||
xopus.close()
|
xopus.close()
|
||||||
print("encoded")
|
progress.desc = "encoded"
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import importlib
|
import importlib
|
||||||
import math
|
import math
|
||||||
import struct
|
import struct
|
||||||
|
|
||||||
import pyogg
|
import pyogg
|
||||||
import os
|
import os
|
||||||
import numpy as np
|
import numpy as np
|
||||||
@ -109,7 +108,6 @@ class DualOpusEncoder:
|
|||||||
|
|
||||||
@return chunk size
|
@return chunk size
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if self.version != "hev2" and size > 60:
|
if self.version != "hev2" and size > 60:
|
||||||
raise ValueError("non hev2 can't use framesize > 60")
|
raise ValueError("non hev2 can't use framesize > 60")
|
||||||
|
|
||||||
@ -336,12 +334,18 @@ class XopusReader:
|
|||||||
if data.startswith(b"\\xeof\\xeof"):
|
if data.startswith(b"\\xeof\\xeof"):
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
yield decoder.decode(data)
|
try:
|
||||||
|
yield decoder.decode(data)
|
||||||
|
except:
|
||||||
|
yield b""
|
||||||
else:
|
else:
|
||||||
decodedlist = []
|
decodedlist = []
|
||||||
for data in self.xopusline[1:]:
|
for data in self.xopusline[1:]:
|
||||||
if data.startswith(b"\\xeof\\xeof"):
|
if data.startswith(b"\\xeof\\xeof"):
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
decodedlist.append(decoder.decode(data))
|
try:
|
||||||
|
decodedlist.append(decoder.decode(data))
|
||||||
|
except:
|
||||||
|
decodedlist.append(b"")
|
||||||
return decodedlist
|
return decodedlist
|
59
player.py
59
player.py
@ -1,25 +1,60 @@
|
|||||||
import pyaudio
|
import pyaudio
|
||||||
from libxheopus import DualOpusDecoder, XopusReader
|
from libxheopus import DualOpusDecoder, XopusReader
|
||||||
|
import argparse
|
||||||
|
from tqdm import tqdm
|
||||||
|
import wave
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description='xHE-Opus Decoder/Player')
|
||||||
|
|
||||||
|
parser.add_argument("input", help='Input xopus file path')
|
||||||
|
parser.add_argument("-o", "--output", help='Output wav int16 file path')
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
progress = tqdm()
|
||||||
|
|
||||||
# Initialize PyAudio
|
# Initialize PyAudio
|
||||||
p = pyaudio.PyAudio()
|
p = pyaudio.PyAudio()
|
||||||
|
|
||||||
decoder = DualOpusDecoder()
|
decoder = DualOpusDecoder()
|
||||||
|
|
||||||
streamoutput = p.open(format=pyaudio.paInt16, channels=2, rate=48000, output=True)
|
xopusdecoder = XopusReader(args.input)
|
||||||
|
|
||||||
xopusdecoder = XopusReader(r"test.xopus")
|
metadata = xopusdecoder.readmetadata()
|
||||||
|
|
||||||
print(xopusdecoder.readmetadata())
|
progress.total = metadata["footer"]["length"]
|
||||||
|
print("\nloudness:", metadata["footer"]["contentloudness"], "DBFS")
|
||||||
|
|
||||||
try:
|
print(metadata["header"])
|
||||||
|
|
||||||
|
if not args.output:
|
||||||
|
progress.desc = "playing..."
|
||||||
|
streamoutput = p.open(format=pyaudio.paInt16, channels=2, rate=48000, output=True)
|
||||||
|
try:
|
||||||
|
for data in xopusdecoder.decode(decoder, True):
|
||||||
|
streamoutput.write(data)
|
||||||
|
|
||||||
|
progress.update(1)
|
||||||
|
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print("Interrupted by user")
|
||||||
|
finally:
|
||||||
|
# Clean up PyAudio streams and terminate PyAudio
|
||||||
|
streamoutput.stop_stream()
|
||||||
|
streamoutput.close()
|
||||||
|
p.terminate()
|
||||||
|
|
||||||
|
progress.desc = "played"
|
||||||
|
else:
|
||||||
|
progress.desc = "converting..."
|
||||||
|
outwav = wave.open("output.wav", "w")
|
||||||
|
# Set the parameters of the WAV file
|
||||||
|
outwav.setnchannels(2) # Mono
|
||||||
|
outwav.setsampwidth(2) # 2 bytes (16 bits) per sample
|
||||||
|
outwav.setframerate(48000)
|
||||||
for data in xopusdecoder.decode(decoder, True):
|
for data in xopusdecoder.decode(decoder, True):
|
||||||
streamoutput.write(data)
|
# Write the audio data to the file
|
||||||
|
outwav.writeframes(data)
|
||||||
|
progress.update(1)
|
||||||
|
|
||||||
except KeyboardInterrupt:
|
progress.desc = "converted"
|
||||||
print("Interrupted by user")
|
|
||||||
finally:
|
|
||||||
# Clean up PyAudio streams and terminate PyAudio
|
|
||||||
streamoutput.stop_stream()
|
|
||||||
streamoutput.close()
|
|
||||||
p.terminate()
|
|
38
readme.md
Normal file
38
readme.md
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
# xHE-Opus
|
||||||
|
xHE-Opus is extended High Efficiency. It use Dual-Encoder to encode per channel and bitrate is divide 2 for per channel.
|
||||||
|
|
||||||
|
# Install
|
||||||
|
[PyOgg (damp11113 moded)](https://github.com/damp11113/PyOgg)
|
||||||
|
|
||||||
|
# Using
|
||||||
|
## Encoder
|
||||||
|
to encode you can use
|
||||||
|
```bash
|
||||||
|
$ python3 encode.py
|
||||||
|
```
|
||||||
|
```bash
|
||||||
|
usage: encode.py [-h] [-sr SAMPRATE] [-b BITRATE] [-c COMPRESS] [-l LOSS] [-fs FRAMESIZE] [-bm BITMODE]
|
||||||
|
[-bw BANDWIDTH] [-a APP] [-v VER] [-pred] [-ph] [-dtx] [-sb]
|
||||||
|
input output
|
||||||
|
encode.py: error: the following arguments are required: input, output
|
||||||
|
```
|
||||||
|
simple example
|
||||||
|
```bash
|
||||||
|
$ python3 encode.py input.wav output.xopus
|
||||||
|
```
|
||||||
|
This will convert to xhe-opus with bitrate 64Kbps (32Kbps per channel), bitrate mode is CVBR, compression is 10 and app is hev2
|
||||||
|
|
||||||
|
or if you want to set bitrate you can use `-b <bitrate>` input bit per sec (bps) like
|
||||||
|
```bash
|
||||||
|
$ python3 encode.py input.wav output.xopus -b 16000
|
||||||
|
```
|
||||||
|
|
||||||
|
## Decoder/Player
|
||||||
|
To player or decode this file you can use
|
||||||
|
```bash
|
||||||
|
$ python3 input.xopus
|
||||||
|
```
|
||||||
|
or if you want only convert to wav you can use
|
||||||
|
```bash
|
||||||
|
$ python3 input.xopus -o output.wav
|
||||||
|
```
|
BIN
test.xopus
BIN
test.xopus
Binary file not shown.
BIN
test2.xopus
Normal file
BIN
test2.xopus
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user