@boruto_vk7/opus-ogg 1.2.0 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.js +3 -2
- package/dist/esm/index.js +2 -1
- package/package.json +1 -1
- package/dist/cjs/src/index.js +0 -177
- package/dist/cjs/src/oggDemuxer.js +0 -169
- package/dist/types/src/index.d.ts +0 -29
- package/dist/types/src/oggDemuxer.d.ts +0 -19
package/dist/cjs/index.js
CHANGED
|
@@ -43,7 +43,8 @@ const http = __importStar(require("node:http"));
|
|
|
43
43
|
const node_child_process_1 = require("node:child_process");
|
|
44
44
|
const node_stream_1 = require("node:stream");
|
|
45
45
|
const os = __importStar(require("node:os"));
|
|
46
|
-
const
|
|
46
|
+
const oggDemuxer_js_1 = require("./oggDemuxer.js");
|
|
47
|
+
// Import the new demuxer
|
|
47
48
|
// Fallback to system ffmpeg if local bin is not found
|
|
48
49
|
let ffmpegPath = 'ffmpeg';
|
|
49
50
|
/**
|
|
@@ -152,7 +153,7 @@ function EngineOgg(input, options = {}) {
|
|
|
152
153
|
* @returns A Readable stream emitting raw Opus packets (Buffers).
|
|
153
154
|
*/
|
|
154
155
|
function OggToOpusStream(oggInput) {
|
|
155
|
-
const demuxer = new
|
|
156
|
+
const demuxer = new oggDemuxer_js_1.OggDemuxer();
|
|
156
157
|
oggInput.pipe(demuxer);
|
|
157
158
|
return demuxer;
|
|
158
159
|
}
|
package/dist/esm/index.js
CHANGED
|
@@ -5,7 +5,8 @@ import * as http from 'node:http';
|
|
|
5
5
|
import { spawn } from 'node:child_process';
|
|
6
6
|
import { Readable, PassThrough } from 'node:stream';
|
|
7
7
|
import * as os from 'node:os';
|
|
8
|
-
import { OggDemuxer } from './oggDemuxer';
|
|
8
|
+
import { OggDemuxer } from './oggDemuxer.js';
|
|
9
|
+
// Import the new demuxer
|
|
9
10
|
// Fallback to system ffmpeg if local bin is not found
|
|
10
11
|
let ffmpegPath = 'ffmpeg';
|
|
11
12
|
/**
|
package/package.json
CHANGED
package/dist/cjs/src/index.js
DELETED
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.EngineOgg = EngineOgg;
|
|
37
|
-
exports.OggToOpusStream = OggToOpusStream;
|
|
38
|
-
exports.EngineOggFile = EngineOggFile;
|
|
39
|
-
const fs = __importStar(require("node:fs"));
|
|
40
|
-
const path = __importStar(require("node:path"));
|
|
41
|
-
const https = __importStar(require("node:https"));
|
|
42
|
-
const http = __importStar(require("node:http"));
|
|
43
|
-
const node_child_process_1 = require("node:child_process");
|
|
44
|
-
const node_stream_1 = require("node:stream");
|
|
45
|
-
const os = __importStar(require("node:os"));
|
|
46
|
-
const oggDemuxer_1 = require("./oggDemuxer"); // Import the new demuxer
|
|
47
|
-
// Fallback to system ffmpeg if local bin is not found
|
|
48
|
-
let ffmpegPath = 'ffmpeg';
|
|
49
|
-
/**
|
|
50
|
-
* Resolves the path to the FFmpeg binary.
|
|
51
|
-
* Priority:
|
|
52
|
-
* 1. Local bin/ folder (downloaded via postinstall)
|
|
53
|
-
* 2. System PATH
|
|
54
|
-
*/
|
|
55
|
-
function resolveFFmpeg() {
|
|
56
|
-
const possiblePaths = [
|
|
57
|
-
path.join(process.cwd(), 'bin', os.platform() === 'win32' ? 'ffmpeg.exe' : 'ffmpeg'),
|
|
58
|
-
path.join(__dirname, '..', '..', 'bin', os.platform() === 'win32' ? 'ffmpeg.exe' : 'ffmpeg'),
|
|
59
|
-
path.join(__dirname, '..', 'bin', os.platform() === 'win32' ? 'ffmpeg.exe' : 'ffmpeg')
|
|
60
|
-
];
|
|
61
|
-
for (const p of possiblePaths) {
|
|
62
|
-
try {
|
|
63
|
-
if (fs.existsSync(p))
|
|
64
|
-
return p;
|
|
65
|
-
}
|
|
66
|
-
catch { /* ignore */ }
|
|
67
|
-
}
|
|
68
|
-
return 'ffmpeg';
|
|
69
|
-
}
|
|
70
|
-
try {
|
|
71
|
-
ffmpegPath = resolveFFmpeg();
|
|
72
|
-
}
|
|
73
|
-
catch {
|
|
74
|
-
ffmpegPath = 'ffmpeg';
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Converts audio to OGG Opus compatible with WhatsApp (iPhone) and Discord.
|
|
78
|
-
* Optimized for ultra-low latency and minimal CPU stress using streaming.
|
|
79
|
-
*/
|
|
80
|
-
function EngineOgg(input, options = {}) {
|
|
81
|
-
const outputStream = new node_stream_1.PassThrough({ highWaterMark: 128 * 1024 });
|
|
82
|
-
const channels = options.forceStereo ? 2 : 1;
|
|
83
|
-
const profile = options.profile || 'voip';
|
|
84
|
-
const bitrate = options.bitrate || (profile === 'audio' ? '128k' : '64k');
|
|
85
|
-
const bin = options.ffmpegPath || ffmpegPath;
|
|
86
|
-
const args = [
|
|
87
|
-
'-hide_banner',
|
|
88
|
-
'-loglevel', 'error',
|
|
89
|
-
'-probesize', '32',
|
|
90
|
-
'-analyzeduration', '0',
|
|
91
|
-
'-i', 'pipe:0',
|
|
92
|
-
'-vn',
|
|
93
|
-
'-c:a', 'libopus',
|
|
94
|
-
'-ac', channels.toString(),
|
|
95
|
-
'-ar', '48000',
|
|
96
|
-
'-b:a', bitrate,
|
|
97
|
-
'-application', profile,
|
|
98
|
-
'-vbr', 'on',
|
|
99
|
-
'-compression_level', '0',
|
|
100
|
-
'-frame_duration', '20',
|
|
101
|
-
'-map_metadata', '-1',
|
|
102
|
-
'-f', 'opus',
|
|
103
|
-
'pipe:1'
|
|
104
|
-
];
|
|
105
|
-
const ffmpeg = (0, node_child_process_1.spawn)(bin, args);
|
|
106
|
-
// Handle Input
|
|
107
|
-
if (typeof input === 'string') {
|
|
108
|
-
if (/^https?:\/\//.test(input)) {
|
|
109
|
-
const lib = input.startsWith('https') ? https : http;
|
|
110
|
-
lib.get(input, { headers: { 'User-Agent': 'Mozilla/5.0' } }, (res) => {
|
|
111
|
-
if (res.statusCode !== 200) {
|
|
112
|
-
outputStream.emit('error', new Error(`HTTP ${res.statusCode}`));
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
|
-
res.pipe(ffmpeg.stdin);
|
|
116
|
-
}).on('error', (err) => {
|
|
117
|
-
outputStream.emit('error', err);
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
else {
|
|
121
|
-
if (!fs.existsSync(input)) {
|
|
122
|
-
outputStream.emit('error', new Error(`File not found: ${input}`));
|
|
123
|
-
}
|
|
124
|
-
else {
|
|
125
|
-
fs.createReadStream(input).pipe(ffmpeg.stdin);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
else if (input instanceof node_stream_1.Readable) {
|
|
130
|
-
input.pipe(ffmpeg.stdin);
|
|
131
|
-
}
|
|
132
|
-
// Handle Output
|
|
133
|
-
ffmpeg.stdout.pipe(outputStream);
|
|
134
|
-
// Error Handling
|
|
135
|
-
ffmpeg.on('error', (err) => {
|
|
136
|
-
if (err.code === 'ENOENT') {
|
|
137
|
-
const msg = `FFmpeg not found at "${bin}". Please ensure it is installed.`;
|
|
138
|
-
outputStream.emit('error', new Error(msg));
|
|
139
|
-
}
|
|
140
|
-
else {
|
|
141
|
-
outputStream.emit('error', err);
|
|
142
|
-
}
|
|
143
|
-
});
|
|
144
|
-
ffmpeg.stdin.on('error', () => { });
|
|
145
|
-
return outputStream;
|
|
146
|
-
}
|
|
147
|
-
/**
|
|
148
|
-
* Converts an Ogg Opus stream into a stream of raw Opus packets,
|
|
149
|
-
* suitable for `@discordjs/voice` with `StreamType.Opus`.
|
|
150
|
-
*
|
|
151
|
-
* @param oggInput A Readable stream containing Ogg Opus data.
|
|
152
|
-
* @returns A Readable stream emitting raw Opus packets (Buffers).
|
|
153
|
-
*/
|
|
154
|
-
function OggToOpusStream(oggInput) {
|
|
155
|
-
const demuxer = new oggDemuxer_1.OggDemuxer();
|
|
156
|
-
oggInput.pipe(demuxer);
|
|
157
|
-
return demuxer;
|
|
158
|
-
}
|
|
159
|
-
/**
|
|
160
|
-
* Legacy support for file-based conversion (Async)
|
|
161
|
-
*/
|
|
162
|
-
async function EngineOggFile(id, input, options = {}) {
|
|
163
|
-
const TEMP_DIR = path.resolve(process.cwd(), 'temp_audio');
|
|
164
|
-
if (!fs.existsSync(TEMP_DIR))
|
|
165
|
-
fs.mkdirSync(TEMP_DIR, { recursive: true });
|
|
166
|
-
const ts = Date.now();
|
|
167
|
-
const outputFile = path.join(TEMP_DIR, `out_${id}_${ts}.ogg`);
|
|
168
|
-
const stream = EngineOgg(input, options);
|
|
169
|
-
const writeStream = fs.createWriteStream(outputFile);
|
|
170
|
-
return new Promise((resolve, reject) => {
|
|
171
|
-
stream.pipe(writeStream);
|
|
172
|
-
writeStream.on('finish', () => resolve(outputFile));
|
|
173
|
-
writeStream.on('error', reject);
|
|
174
|
-
stream.on('error', reject);
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
exports.default = EngineOgg;
|
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.OggDemuxer = void 0;
|
|
4
|
-
const node_stream_1 = require("node:stream");
|
|
5
|
-
// Constants for Ogg parsing
|
|
6
|
-
const OGG_CAPTURE_PATTERN = 0x4f676753; // 'OggS'
|
|
7
|
-
const OGG_HEADER_SIZE = 27; // Fixed size of Ogg page header
|
|
8
|
-
// Opus header types
|
|
9
|
-
const OPUS_HEAD_SIGNATURE = Buffer.from('OpusHead');
|
|
10
|
-
const OPUS_TAGS_SIGNATURE = Buffer.from('OpusTags');
|
|
11
|
-
/**
|
|
12
|
-
* A Transform stream that demuxes Ogg Opus streams, extracting raw Opus packets.
|
|
13
|
-
* It parses Ogg pages and emits individual Opus packets as Buffers.
|
|
14
|
-
*/
|
|
15
|
-
class OggDemuxer extends node_stream_1.Transform {
|
|
16
|
-
buffer;
|
|
17
|
-
currentGranulePosition;
|
|
18
|
-
bitstreamSerialNumber;
|
|
19
|
-
pageSequenceNumber;
|
|
20
|
-
opusHeadParsed;
|
|
21
|
-
opusTagsParsed;
|
|
22
|
-
constructor() {
|
|
23
|
-
super({ readableObjectMode: true }); // Emits Opus packets as objects (Buffers)
|
|
24
|
-
this.buffer = Buffer.alloc(0);
|
|
25
|
-
this.currentGranulePosition = 0n;
|
|
26
|
-
this.bitstreamSerialNumber = null;
|
|
27
|
-
this.pageSequenceNumber = 0;
|
|
28
|
-
this.opusHeadParsed = false;
|
|
29
|
-
this.opusTagsParsed = false;
|
|
30
|
-
}
|
|
31
|
-
_transform(chunk, encoding, callback) {
|
|
32
|
-
this.buffer = Buffer.concat([this.buffer, chunk]);
|
|
33
|
-
this.parseBuffer();
|
|
34
|
-
callback();
|
|
35
|
-
}
|
|
36
|
-
_flush(callback) {
|
|
37
|
-
// Attempt to parse any remaining data in the buffer
|
|
38
|
-
this.parseBuffer();
|
|
39
|
-
if (this.buffer.length > 0) {
|
|
40
|
-
this.emit('warn', `OggDemuxer: Remaining unparsed data in buffer: ${this.buffer.length} bytes`);
|
|
41
|
-
}
|
|
42
|
-
callback();
|
|
43
|
-
}
|
|
44
|
-
parseBuffer() {
|
|
45
|
-
while (this.buffer.length >= OGG_HEADER_SIZE) {
|
|
46
|
-
const header = this.parsePageHeader(this.buffer);
|
|
47
|
-
if (!header) {
|
|
48
|
-
// No valid OggS pattern found at current position, try to resync
|
|
49
|
-
const nextOggS = this.buffer.indexOf(Buffer.from("OggS"), 1); // Search from next byte
|
|
50
|
-
if (nextOggS === -1) {
|
|
51
|
-
// No more OggS patterns, clear buffer and wait for more data
|
|
52
|
-
this.buffer = Buffer.alloc(0);
|
|
53
|
-
break;
|
|
54
|
-
}
|
|
55
|
-
else {
|
|
56
|
-
// Resync: discard data until next OggS
|
|
57
|
-
this.emit("debug", `OggDemuxer: Resyncing, discarding ${nextOggS} bytes.`);
|
|
58
|
-
this.buffer = this.buffer.subarray(nextOggS);
|
|
59
|
-
continue;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
const pageLength = OGG_HEADER_SIZE + header.pageSegments + header.segmentTable.reduce((a, b) => a + b, 0);
|
|
63
|
-
if (this.buffer.length < pageLength) {
|
|
64
|
-
// Not enough data for the full page, wait for more
|
|
65
|
-
break;
|
|
66
|
-
}
|
|
67
|
-
// Validate bitstream serial number for logical stream continuity
|
|
68
|
-
if (this.bitstreamSerialNumber === null) {
|
|
69
|
-
this.bitstreamSerialNumber = header.bitstreamSerialNumber;
|
|
70
|
-
}
|
|
71
|
-
else if (this.bitstreamSerialNumber !== header.bitstreamSerialNumber) {
|
|
72
|
-
// This indicates a new logical bitstream, which is fine for concatenated Ogg files
|
|
73
|
-
// For simplicity, we'll just reset state for the new stream
|
|
74
|
-
this.bitstreamSerialNumber = header.bitstreamSerialNumber;
|
|
75
|
-
this.opusHeadParsed = false;
|
|
76
|
-
this.opusTagsParsed = false;
|
|
77
|
-
this.pageSequenceNumber = 0;
|
|
78
|
-
this.currentGranulePosition = 0n;
|
|
79
|
-
this.emit('warn', `OggDemuxer: Detected new logical bitstream (serial: ${header.bitstreamSerialNumber})`);
|
|
80
|
-
}
|
|
81
|
-
// Check page sequence number for continuity (optional, but good for error detection)
|
|
82
|
-
if (!(header.headerTypeFlag & 0x02) && header.pageSequenceNumber !== this.pageSequenceNumber) {
|
|
83
|
-
this.emit("warn", `OggDemuxer: Page sequence discontinuity detected. Expected ${this.pageSequenceNumber}, got ${header.pageSequenceNumber}.`);
|
|
84
|
-
// We can still try to process, but this might indicate corruption
|
|
85
|
-
}
|
|
86
|
-
this.pageSequenceNumber = header.pageSequenceNumber + 1;
|
|
87
|
-
this.currentGranulePosition = header.granulePosition;
|
|
88
|
-
// Extract packet data
|
|
89
|
-
let packetOffset = OGG_HEADER_SIZE + header.pageSegments;
|
|
90
|
-
let currentPacketBuffer = Buffer.alloc(0);
|
|
91
|
-
for (let i = 0; i < header.segmentTable.length; i++) {
|
|
92
|
-
const segmentLength = header.segmentTable[i];
|
|
93
|
-
const segmentData = this.buffer.subarray(packetOffset, packetOffset + segmentLength);
|
|
94
|
-
currentPacketBuffer = Buffer.concat([currentPacketBuffer, segmentData]);
|
|
95
|
-
packetOffset += segmentLength;
|
|
96
|
-
// If segment is less than 255, it's the end of a packet
|
|
97
|
-
if (segmentLength < 255 || i === header.segmentTable.length - 1) {
|
|
98
|
-
this.processPacket(currentPacketBuffer);
|
|
99
|
-
currentPacketBuffer = Buffer.alloc(0);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
// Remove processed page from buffer
|
|
103
|
-
this.buffer = this.buffer.subarray(pageLength);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
parsePageHeader(buffer) {
|
|
107
|
-
// Check capture pattern 'OggS'
|
|
108
|
-
// OGG_CAPTURE_PATTERN is 0x4f676753. buffer.readUInt32LE(0) reads 0x5367674f on little-endian systems.
|
|
109
|
-
// So we need to compare with Buffer.from("OggS").readUInt32LE(0)
|
|
110
|
-
if (buffer.readUInt32LE(0) !== Buffer.from("OggS").readUInt32LE(0)) {
|
|
111
|
-
return null;
|
|
112
|
-
}
|
|
113
|
-
const header = {
|
|
114
|
-
capturePattern: buffer.readUInt32LE(0),
|
|
115
|
-
streamStructureVersion: buffer.readUInt8(4),
|
|
116
|
-
headerTypeFlag: buffer.readUInt8(5),
|
|
117
|
-
granulePosition: buffer.readBigInt64LE(6),
|
|
118
|
-
bitstreamSerialNumber: buffer.readUInt32LE(14),
|
|
119
|
-
pageSequenceNumber: buffer.readUInt32LE(18),
|
|
120
|
-
pageChecksum: buffer.readUInt32LE(22),
|
|
121
|
-
pageSegments: buffer.readUInt8(26),
|
|
122
|
-
segmentTable: [],
|
|
123
|
-
};
|
|
124
|
-
// Read segment table
|
|
125
|
-
const segmentTableOffset = OGG_HEADER_SIZE;
|
|
126
|
-
for (let i = 0; i < header.pageSegments; i++) {
|
|
127
|
-
header.segmentTable.push(buffer.readUInt8(segmentTableOffset + i));
|
|
128
|
-
}
|
|
129
|
-
return header;
|
|
130
|
-
}
|
|
131
|
-
processPacket(packet) {
|
|
132
|
-
// The first two packets in an Ogg Opus stream are OpusHead and OpusTags
|
|
133
|
-
if (!this.opusHeadParsed) {
|
|
134
|
-
if (packet.subarray(0, 8).equals(OPUS_HEAD_SIGNATURE)) {
|
|
135
|
-
// This is the OpusHead packet (identification header)
|
|
136
|
-
// We don't need to emit it as a raw Opus frame for @discordjs/voice
|
|
137
|
-
this.opusHeadParsed = true;
|
|
138
|
-
this.emit("debug", `OggDemuxer: Parsed OpusHead packet. Length: ${packet.length}`);
|
|
139
|
-
}
|
|
140
|
-
else {
|
|
141
|
-
this.emit("warn", `OggDemuxer: Expected OpusHead packet but got something else. Packet length: ${packet.length}, first 8 bytes: ${packet.subarray(0, 8).toString()}`);
|
|
142
|
-
// Potentially a malformed stream or not an Opus stream
|
|
143
|
-
}
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
146
|
-
if (!this.opusTagsParsed) {
|
|
147
|
-
if (packet.subarray(0, 8).equals(OPUS_TAGS_SIGNATURE)) {
|
|
148
|
-
// This is the OpusTags packet (comment header)
|
|
149
|
-
// We don't need to emit it as a raw Opus frame for @discordjs/voice
|
|
150
|
-
this.opusTagsParsed = true;
|
|
151
|
-
this.emit("debug", `OggDemuxer: Parsed OpusTags packet. Length: ${packet.length}`);
|
|
152
|
-
}
|
|
153
|
-
else {
|
|
154
|
-
this.emit("warn", `OggDemuxer: Expected OpusTags packet but got something else. Packet length: ${packet.length}, first 8 bytes: ${packet.subarray(0, 8).toString()}`);
|
|
155
|
-
// Potentially a malformed stream or not an Opus stream
|
|
156
|
-
}
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
159
|
-
// After OpusHead and OpusTags, all subsequent packets are raw Opus frames
|
|
160
|
-
if (this.opusHeadParsed && this.opusTagsParsed) {
|
|
161
|
-
this.emit("debug", `OggDemuxer: Emitting Opus packet. Length: ${packet.length}`);
|
|
162
|
-
this.push(packet);
|
|
163
|
-
}
|
|
164
|
-
else {
|
|
165
|
-
this.emit("debug", `OggDemuxer: Skipping non-Opus data before headers. Length: ${packet.length}`);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
exports.OggDemuxer = OggDemuxer;
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { Readable } from 'node:stream';
|
|
2
|
-
/**
|
|
3
|
-
* EngineOgg Configuration Options
|
|
4
|
-
*/
|
|
5
|
-
export interface EngineOggOptions {
|
|
6
|
-
profile?: 'voip' | 'audio';
|
|
7
|
-
forceStereo?: boolean;
|
|
8
|
-
bitrate?: string;
|
|
9
|
-
preset?: string;
|
|
10
|
-
ffmpegPath?: string;
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* Converts audio to OGG Opus compatible with WhatsApp (iPhone) and Discord.
|
|
14
|
-
* Optimized for ultra-low latency and minimal CPU stress using streaming.
|
|
15
|
-
*/
|
|
16
|
-
export declare function EngineOgg(input: string | Readable, options?: EngineOggOptions): Readable;
|
|
17
|
-
/**
|
|
18
|
-
* Converts an Ogg Opus stream into a stream of raw Opus packets,
|
|
19
|
-
* suitable for `@discordjs/voice` with `StreamType.Opus`.
|
|
20
|
-
*
|
|
21
|
-
* @param oggInput A Readable stream containing Ogg Opus data.
|
|
22
|
-
* @returns A Readable stream emitting raw Opus packets (Buffers).
|
|
23
|
-
*/
|
|
24
|
-
export declare function OggToOpusStream(oggInput: Readable): Readable;
|
|
25
|
-
/**
|
|
26
|
-
* Legacy support for file-based conversion (Async)
|
|
27
|
-
*/
|
|
28
|
-
export declare function EngineOggFile(id: string | number, input: string | Readable, options?: EngineOggOptions): Promise<string>;
|
|
29
|
-
export default EngineOgg;
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { Transform, TransformCallback } from 'node:stream';
|
|
2
|
-
/**
|
|
3
|
-
* A Transform stream that demuxes Ogg Opus streams, extracting raw Opus packets.
|
|
4
|
-
* It parses Ogg pages and emits individual Opus packets as Buffers.
|
|
5
|
-
*/
|
|
6
|
-
export declare class OggDemuxer extends Transform {
|
|
7
|
-
private buffer;
|
|
8
|
-
private currentGranulePosition;
|
|
9
|
-
private bitstreamSerialNumber;
|
|
10
|
-
private pageSequenceNumber;
|
|
11
|
-
private opusHeadParsed;
|
|
12
|
-
private opusTagsParsed;
|
|
13
|
-
constructor();
|
|
14
|
-
_transform(chunk: Buffer, encoding: BufferEncoding, callback: TransformCallback): void;
|
|
15
|
-
_flush(callback: TransformCallback): void;
|
|
16
|
-
private parseBuffer;
|
|
17
|
-
private parsePageHeader;
|
|
18
|
-
private processPacket;
|
|
19
|
-
}
|