@absolutejs/voice 0.0.22-beta.322 → 0.0.22-beta.323

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/vue/index.js CHANGED
@@ -4768,6 +4768,63 @@ var stringStat = (stat, key) => {
4768
4768
  };
4769
4769
  var statKey = (stat) => String(stat.id ?? stringStat(stat, "ssrc") ?? numericStat(stat, "ssrc") ?? stringStat(stat, "trackIdentifier") ?? stringStat(stat, "mid") ?? "unknown");
4770
4770
  var secondsToMs = (value) => value === undefined ? undefined : value * 1000;
4771
+ var DEFAULT_TELEPHONY_FORMAT = {
4772
+ channels: 1,
4773
+ container: "raw",
4774
+ encoding: "mulaw",
4775
+ sampleRateHz: 8000
4776
+ };
4777
+ var bytesToBase64 = (audio) => {
4778
+ const bytes = audio instanceof ArrayBuffer ? new Uint8Array(audio) : new Uint8Array(audio.buffer, audio.byteOffset, audio.byteLength);
4779
+ return Buffer.from(bytes).toString("base64");
4780
+ };
4781
+ var base64ToBytes = (value) => new Uint8Array(Buffer.from(value, "base64"));
4782
+ var unknownRecord = (value) => value && typeof value === "object" ? value : {};
4783
+ var firstString = (records, keys) => {
4784
+ for (const record of records) {
4785
+ for (const key of keys) {
4786
+ const value = record[key];
4787
+ if (typeof value === "string" && value.length > 0) {
4788
+ return value;
4789
+ }
4790
+ if (typeof value === "number" && Number.isFinite(value)) {
4791
+ return String(value);
4792
+ }
4793
+ }
4794
+ }
4795
+ return;
4796
+ };
4797
+ var firstNumber = (records, keys) => {
4798
+ for (const record of records) {
4799
+ for (const key of keys) {
4800
+ const value = record[key];
4801
+ if (typeof value === "number" && Number.isFinite(value)) {
4802
+ return value;
4803
+ }
4804
+ if (typeof value === "string") {
4805
+ const parsed = Number(value);
4806
+ if (Number.isFinite(parsed)) {
4807
+ return parsed;
4808
+ }
4809
+ }
4810
+ }
4811
+ }
4812
+ return;
4813
+ };
4814
+ var telephonyDirection = (track) => {
4815
+ const normalized = track?.toLowerCase();
4816
+ if (!normalized) {
4817
+ return "unknown";
4818
+ }
4819
+ if (normalized.includes("inbound") || normalized.includes("caller") || normalized.includes("in")) {
4820
+ return "inbound";
4821
+ }
4822
+ if (normalized.includes("outbound") || normalized.includes("assistant") || normalized.includes("out")) {
4823
+ return "outbound";
4824
+ }
4825
+ return "unknown";
4826
+ };
4827
+ var telephonyFrameKind = (direction) => direction === "outbound" ? "assistant-audio" : "input-audio";
4771
4828
  var normalizeWebRTCStat = (stat) => {
4772
4829
  const sample = {};
4773
4830
  for (const [key, value] of Object.entries(stat)) {
@@ -4777,6 +4834,113 @@ var normalizeWebRTCStat = (stat) => {
4777
4834
  }
4778
4835
  return sample;
4779
4836
  };
4837
+ var parseTelephonyMediaFrame = (input) => {
4838
+ const envelope = input.envelope;
4839
+ const media = unknownRecord(envelope.media);
4840
+ const payload = firstString([media, envelope], ["payload", "audio", "data"]) ?? firstString([unknownRecord(envelope.message)], ["payload"]);
4841
+ if (!payload) {
4842
+ return;
4843
+ }
4844
+ const carrier = input.carrier ?? firstString([envelope], ["provider"]) ?? "telephony";
4845
+ const streamId = firstString([media, envelope], ["streamSid", "stream_id", "streamId", "streamId", "callSid", "call_id"]);
4846
+ const sequenceNumber = firstString([media, envelope], ["sequenceNumber", "sequence_number", "chunk"]);
4847
+ const track = firstString([media, envelope], ["track", "direction"]);
4848
+ const direction = telephonyDirection(track);
4849
+ const timestamp = firstNumber([media, envelope], ["timestamp", "time", "startedAt"]);
4850
+ return {
4851
+ at: timestamp,
4852
+ audio: base64ToBytes(payload),
4853
+ format: input.format ?? DEFAULT_TELEPHONY_FORMAT,
4854
+ id: [
4855
+ carrier,
4856
+ streamId ?? input.sessionId ?? "stream",
4857
+ sequenceNumber ?? timestamp ?? Date.now()
4858
+ ].join(":"),
4859
+ kind: telephonyFrameKind(direction),
4860
+ metadata: {
4861
+ carrier,
4862
+ direction,
4863
+ event: firstString([envelope], ["event", "type"]),
4864
+ sequenceNumber,
4865
+ streamId,
4866
+ track
4867
+ },
4868
+ sessionId: input.sessionId ?? streamId,
4869
+ source: "telephony"
4870
+ };
4871
+ };
4872
+ var serializeTelephonyMediaFrame = (input) => {
4873
+ const carrier = input.carrier ?? input.frame.metadata?.carrier ?? "telephony";
4874
+ const streamId = input.streamId ?? (typeof input.frame.metadata?.streamId === "string" ? input.frame.metadata.streamId : input.frame.sessionId);
4875
+ const sequenceNumber = input.sequenceNumber ?? (typeof input.frame.metadata?.sequenceNumber === "string" || typeof input.frame.metadata?.sequenceNumber === "number" ? input.frame.metadata.sequenceNumber : undefined);
4876
+ const direction = input.frame.kind === "assistant-audio" ? "outbound" : "inbound";
4877
+ const payload = input.frame.audio ? bytesToBase64(input.frame.audio) : "";
4878
+ if (carrier === "twilio") {
4879
+ return {
4880
+ event: "media",
4881
+ sequenceNumber,
4882
+ streamSid: streamId,
4883
+ media: {
4884
+ payload,
4885
+ timestamp: input.frame.at,
4886
+ track: direction
4887
+ }
4888
+ };
4889
+ }
4890
+ if (carrier === "telnyx") {
4891
+ return {
4892
+ event: "media",
4893
+ stream_id: streamId,
4894
+ sequence_number: sequenceNumber,
4895
+ media: {
4896
+ payload,
4897
+ timestamp: input.frame.at,
4898
+ track: direction
4899
+ }
4900
+ };
4901
+ }
4902
+ if (carrier === "plivo") {
4903
+ return {
4904
+ event: "media",
4905
+ streamId,
4906
+ sequenceNumber,
4907
+ media: {
4908
+ payload,
4909
+ timestamp: input.frame.at,
4910
+ track: direction
4911
+ }
4912
+ };
4913
+ }
4914
+ return {
4915
+ event: "media",
4916
+ provider: carrier,
4917
+ sequenceNumber,
4918
+ streamId,
4919
+ media: {
4920
+ payload,
4921
+ timestamp: input.frame.at,
4922
+ track: direction
4923
+ }
4924
+ };
4925
+ };
4926
+ var createTelephonyMediaSerializer = (input) => {
4927
+ const format = input.format ?? DEFAULT_TELEPHONY_FORMAT;
4928
+ return {
4929
+ carrier: input.carrier,
4930
+ format,
4931
+ parse: (envelope) => parseTelephonyMediaFrame({
4932
+ carrier: input.carrier,
4933
+ envelope,
4934
+ format,
4935
+ sessionId: input.sessionId ?? input.streamId
4936
+ }),
4937
+ serialize: (frame) => serializeTelephonyMediaFrame({
4938
+ carrier: input.carrier,
4939
+ frame,
4940
+ streamId: input.streamId
4941
+ })
4942
+ };
4943
+ };
4780
4944
  var buildMediaResamplingPlan = (input) => {
4781
4945
  const required = !formatMatches(input.inputFormat, input.outputFormat);
4782
4946
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.322",
3
+ "version": "0.0.22-beta.323",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",
@@ -246,7 +246,7 @@
246
246
  }
247
247
  },
248
248
  "dependencies": {
249
- "@absolutejs/media": "0.0.1-beta.5"
249
+ "@absolutejs/media": "0.0.1-beta.6"
250
250
  },
251
251
  "devDependencies": {
252
252
  "@absolutejs/absolute": "0.19.0-beta.646",