vidply 1.0.7 → 1.0.8

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.
@@ -5469,6 +5469,9 @@ var Player = class extends EventEmitter {
5469
5469
  this.audioDescriptionSrc = this.options.audioDescriptionSrc;
5470
5470
  this.signLanguageSrc = this.options.signLanguageSrc;
5471
5471
  this.signLanguageVideo = null;
5472
+ this.audioDescriptionSourceElement = null;
5473
+ this.originalAudioDescriptionSource = null;
5474
+ this.audioDescriptionCaptionTracks = [];
5472
5475
  this.container = null;
5473
5476
  this.renderer = null;
5474
5477
  this.controlBar = null;
@@ -5623,6 +5626,53 @@ var Player = class extends EventEmitter {
5623
5626
  if (!src) {
5624
5627
  throw new Error("No media source found");
5625
5628
  }
5629
+ const sourceElements = this.element.querySelectorAll("source");
5630
+ for (const sourceEl of sourceElements) {
5631
+ const descSrc = sourceEl.getAttribute("data-desc-src");
5632
+ const origSrc = sourceEl.getAttribute("data-orig-src");
5633
+ if (descSrc || origSrc) {
5634
+ if (!this.audioDescriptionSourceElement) {
5635
+ this.audioDescriptionSourceElement = sourceEl;
5636
+ }
5637
+ if (origSrc) {
5638
+ if (!this.originalAudioDescriptionSource) {
5639
+ this.originalAudioDescriptionSource = origSrc;
5640
+ }
5641
+ if (!this.originalSrc) {
5642
+ this.originalSrc = origSrc;
5643
+ }
5644
+ } else {
5645
+ const currentSrcAttr = sourceEl.getAttribute("src");
5646
+ if (!this.originalAudioDescriptionSource && currentSrcAttr) {
5647
+ this.originalAudioDescriptionSource = currentSrcAttr;
5648
+ }
5649
+ if (!this.originalSrc && currentSrcAttr) {
5650
+ this.originalSrc = currentSrcAttr;
5651
+ }
5652
+ }
5653
+ if (descSrc && !this.audioDescriptionSrc) {
5654
+ this.audioDescriptionSrc = descSrc;
5655
+ }
5656
+ }
5657
+ }
5658
+ const trackElements = this.element.querySelectorAll("track");
5659
+ trackElements.forEach((trackEl) => {
5660
+ const trackKind = trackEl.getAttribute("kind");
5661
+ const trackDescSrc = trackEl.getAttribute("data-desc-src");
5662
+ if (trackKind === "captions" || trackKind === "subtitles" || trackKind === "chapters") {
5663
+ if (trackDescSrc) {
5664
+ this.audioDescriptionCaptionTracks.push({
5665
+ trackElement: trackEl,
5666
+ originalSrc: trackEl.getAttribute("src"),
5667
+ describedSrc: trackDescSrc,
5668
+ originalTrackSrc: trackEl.getAttribute("data-orig-src") || trackEl.getAttribute("src"),
5669
+ explicit: true
5670
+ // Explicitly defined, so we should validate it
5671
+ });
5672
+ this.log(`Found explicit described ${trackKind} track: ${trackEl.getAttribute("src")} -> ${trackDescSrc}`);
5673
+ }
5674
+ }
5675
+ });
5626
5676
  if (!this.originalSrc) {
5627
5677
  this.originalSrc = src;
5628
5678
  }
@@ -5907,15 +5957,396 @@ var Player = class extends EventEmitter {
5907
5957
  this.enableCaptions();
5908
5958
  }
5909
5959
  }
5960
+ /**
5961
+ * Check if a track file exists
5962
+ * @param {string} url - Track file URL
5963
+ * @returns {Promise<boolean>} - True if file exists
5964
+ */
5965
+ async validateTrackExists(url) {
5966
+ try {
5967
+ const response = await fetch(url, { method: "HEAD", cache: "no-cache" });
5968
+ return response.ok;
5969
+ } catch (error) {
5970
+ return false;
5971
+ }
5972
+ }
5910
5973
  // Audio Description
5911
5974
  async enableAudioDescription() {
5912
- if (!this.audioDescriptionSrc) {
5913
- console.warn("VidPly: No audio description source provided");
5975
+ const hasSourceElementsWithDesc = Array.from(this.element.querySelectorAll("source")).some((el) => el.getAttribute("data-desc-src"));
5976
+ const hasTracksWithDesc = this.audioDescriptionCaptionTracks.length > 0;
5977
+ if (!this.audioDescriptionSrc && !hasSourceElementsWithDesc && !hasTracksWithDesc) {
5978
+ console.warn("VidPly: No audio description source, source elements, or tracks provided");
5914
5979
  return;
5915
5980
  }
5916
5981
  const currentTime = this.state.currentTime;
5917
5982
  const wasPlaying = this.state.playing;
5918
- this.element.src = this.audioDescriptionSrc;
5983
+ let swappedTracksForTranscript = [];
5984
+ if (this.audioDescriptionSourceElement) {
5985
+ const currentSrc = this.element.currentSrc || this.element.src;
5986
+ const sourceElements = Array.from(this.element.querySelectorAll("source"));
5987
+ let sourceElementToUpdate = null;
5988
+ let descSrc = this.audioDescriptionSrc;
5989
+ for (const sourceEl of sourceElements) {
5990
+ const sourceSrc = sourceEl.getAttribute("src");
5991
+ const descSrcAttr = sourceEl.getAttribute("data-desc-src");
5992
+ const sourceFilename = sourceSrc ? sourceSrc.split("/").pop() : "";
5993
+ const currentFilename = currentSrc ? currentSrc.split("/").pop() : "";
5994
+ if (currentSrc && (currentSrc === sourceSrc || currentSrc.includes(sourceSrc) || currentSrc.includes(sourceFilename) || sourceFilename && currentFilename === sourceFilename)) {
5995
+ sourceElementToUpdate = sourceEl;
5996
+ if (descSrcAttr) {
5997
+ descSrc = descSrcAttr;
5998
+ } else if (sourceSrc) {
5999
+ descSrc = this.audioDescriptionSrc || descSrc;
6000
+ }
6001
+ break;
6002
+ }
6003
+ }
6004
+ if (!sourceElementToUpdate) {
6005
+ sourceElementToUpdate = this.audioDescriptionSourceElement;
6006
+ const storedDescSrc = sourceElementToUpdate.getAttribute("data-desc-src");
6007
+ if (storedDescSrc) {
6008
+ descSrc = storedDescSrc;
6009
+ }
6010
+ }
6011
+ if (this.audioDescriptionCaptionTracks.length > 0) {
6012
+ const validationPromises = this.audioDescriptionCaptionTracks.map(async (trackInfo) => {
6013
+ if (trackInfo.trackElement && trackInfo.describedSrc) {
6014
+ if (trackInfo.explicit === true) {
6015
+ try {
6016
+ const exists = await this.validateTrackExists(trackInfo.describedSrc);
6017
+ return { trackInfo, exists };
6018
+ } catch (error) {
6019
+ return { trackInfo, exists: false };
6020
+ }
6021
+ } else {
6022
+ return { trackInfo, exists: false };
6023
+ }
6024
+ }
6025
+ return { trackInfo, exists: false };
6026
+ });
6027
+ const validationResults = await Promise.all(validationPromises);
6028
+ const tracksToSwap = validationResults.filter((result) => result.exists);
6029
+ if (tracksToSwap.length > 0) {
6030
+ const trackModes = /* @__PURE__ */ new Map();
6031
+ tracksToSwap.forEach(({ trackInfo }) => {
6032
+ const textTrack = trackInfo.trackElement.track;
6033
+ if (textTrack) {
6034
+ trackModes.set(trackInfo, {
6035
+ wasShowing: textTrack.mode === "showing",
6036
+ wasHidden: textTrack.mode === "hidden"
6037
+ });
6038
+ } else {
6039
+ trackModes.set(trackInfo, {
6040
+ wasShowing: false,
6041
+ wasHidden: false
6042
+ });
6043
+ }
6044
+ });
6045
+ const tracksToReadd = tracksToSwap.map(({ trackInfo }) => {
6046
+ const oldSrc = trackInfo.trackElement.getAttribute("src");
6047
+ const parent = trackInfo.trackElement.parentNode;
6048
+ const nextSibling = trackInfo.trackElement.nextSibling;
6049
+ const attributes = {};
6050
+ Array.from(trackInfo.trackElement.attributes).forEach((attr) => {
6051
+ attributes[attr.name] = attr.value;
6052
+ });
6053
+ return {
6054
+ trackInfo,
6055
+ oldSrc,
6056
+ parent,
6057
+ nextSibling,
6058
+ attributes
6059
+ };
6060
+ });
6061
+ tracksToReadd.forEach(({ trackInfo }) => {
6062
+ trackInfo.trackElement.remove();
6063
+ });
6064
+ this.element.load();
6065
+ setTimeout(() => {
6066
+ tracksToReadd.forEach(({ trackInfo, oldSrc, parent, nextSibling, attributes }) => {
6067
+ swappedTracksForTranscript.push(trackInfo);
6068
+ const newTrackElement = document.createElement("track");
6069
+ newTrackElement.setAttribute("src", trackInfo.describedSrc);
6070
+ Object.keys(attributes).forEach((attrName) => {
6071
+ if (attrName !== "src" && attrName !== "data-desc-src") {
6072
+ newTrackElement.setAttribute(attrName, attributes[attrName]);
6073
+ }
6074
+ });
6075
+ if (nextSibling && nextSibling.parentNode) {
6076
+ parent.insertBefore(newTrackElement, nextSibling);
6077
+ } else {
6078
+ parent.appendChild(newTrackElement);
6079
+ }
6080
+ trackInfo.trackElement = newTrackElement;
6081
+ });
6082
+ this.element.load();
6083
+ const setupNewTracks = () => {
6084
+ setTimeout(() => {
6085
+ swappedTracksForTranscript.forEach((trackInfo) => {
6086
+ const trackElement = trackInfo.trackElement;
6087
+ const newTextTrack = trackElement.track;
6088
+ if (newTextTrack) {
6089
+ const modeInfo = trackModes.get(trackInfo) || { wasShowing: false, wasHidden: false };
6090
+ newTextTrack.mode = "hidden";
6091
+ const restoreMode = () => {
6092
+ if (modeInfo.wasShowing) {
6093
+ newTextTrack.mode = "hidden";
6094
+ } else if (modeInfo.wasHidden) {
6095
+ newTextTrack.mode = "hidden";
6096
+ } else {
6097
+ newTextTrack.mode = "disabled";
6098
+ }
6099
+ };
6100
+ if (newTextTrack.readyState >= 2) {
6101
+ restoreMode();
6102
+ } else {
6103
+ newTextTrack.addEventListener("load", restoreMode, { once: true });
6104
+ newTextTrack.addEventListener("error", restoreMode, { once: true });
6105
+ }
6106
+ }
6107
+ });
6108
+ }, 300);
6109
+ };
6110
+ if (this.element.readyState >= 1) {
6111
+ setTimeout(setupNewTracks, 200);
6112
+ } else {
6113
+ this.element.addEventListener("loadedmetadata", setupNewTracks, { once: true });
6114
+ setTimeout(setupNewTracks, 2e3);
6115
+ }
6116
+ }, 100);
6117
+ const skippedCount = validationResults.length - tracksToSwap.length;
6118
+ }
6119
+ }
6120
+ const allSourceElements = Array.from(this.element.querySelectorAll("source"));
6121
+ const sourcesToUpdate = [];
6122
+ allSourceElements.forEach((sourceEl) => {
6123
+ const descSrcAttr = sourceEl.getAttribute("data-desc-src");
6124
+ const currentSrc2 = sourceEl.getAttribute("src");
6125
+ if (descSrcAttr) {
6126
+ const type = sourceEl.getAttribute("type");
6127
+ let origSrc = sourceEl.getAttribute("data-orig-src");
6128
+ if (!origSrc) {
6129
+ origSrc = currentSrc2;
6130
+ }
6131
+ sourcesToUpdate.push({
6132
+ src: descSrcAttr,
6133
+ // Use described version
6134
+ type,
6135
+ origSrc,
6136
+ descSrc: descSrcAttr
6137
+ });
6138
+ } else {
6139
+ const type = sourceEl.getAttribute("type");
6140
+ const src = sourceEl.getAttribute("src");
6141
+ sourcesToUpdate.push({
6142
+ src,
6143
+ type,
6144
+ origSrc: null,
6145
+ descSrc: null
6146
+ });
6147
+ }
6148
+ });
6149
+ allSourceElements.forEach((sourceEl) => {
6150
+ sourceEl.remove();
6151
+ });
6152
+ sourcesToUpdate.forEach((sourceInfo) => {
6153
+ const newSource = document.createElement("source");
6154
+ newSource.setAttribute("src", sourceInfo.src);
6155
+ if (sourceInfo.type) {
6156
+ newSource.setAttribute("type", sourceInfo.type);
6157
+ }
6158
+ if (sourceInfo.origSrc) {
6159
+ newSource.setAttribute("data-orig-src", sourceInfo.origSrc);
6160
+ }
6161
+ if (sourceInfo.descSrc) {
6162
+ newSource.setAttribute("data-desc-src", sourceInfo.descSrc);
6163
+ }
6164
+ this.element.appendChild(newSource);
6165
+ });
6166
+ this.element.load();
6167
+ await new Promise((resolve) => {
6168
+ const onLoadedMetadata = () => {
6169
+ this.element.removeEventListener("loadedmetadata", onLoadedMetadata);
6170
+ resolve();
6171
+ };
6172
+ this.element.addEventListener("loadedmetadata", onLoadedMetadata);
6173
+ });
6174
+ await new Promise((resolve) => setTimeout(resolve, 300));
6175
+ if (this.element.tagName === "VIDEO" && currentTime === 0 && !wasPlaying) {
6176
+ if (this.element.readyState >= 1) {
6177
+ this.element.currentTime = 1e-3;
6178
+ setTimeout(() => {
6179
+ this.element.currentTime = 0;
6180
+ }, 10);
6181
+ }
6182
+ }
6183
+ this.seek(currentTime);
6184
+ if (wasPlaying) {
6185
+ this.play();
6186
+ }
6187
+ this.state.audioDescriptionEnabled = true;
6188
+ this.emit("audiodescriptionenabled");
6189
+ } else {
6190
+ if (this.audioDescriptionCaptionTracks.length > 0) {
6191
+ const validationPromises = this.audioDescriptionCaptionTracks.map(async (trackInfo) => {
6192
+ if (trackInfo.trackElement && trackInfo.describedSrc) {
6193
+ if (trackInfo.explicit === true) {
6194
+ try {
6195
+ const exists = await this.validateTrackExists(trackInfo.describedSrc);
6196
+ return { trackInfo, exists };
6197
+ } catch (error) {
6198
+ return { trackInfo, exists: false };
6199
+ }
6200
+ } else {
6201
+ return { trackInfo, exists: false };
6202
+ }
6203
+ }
6204
+ return { trackInfo, exists: false };
6205
+ });
6206
+ const validationResults = await Promise.all(validationPromises);
6207
+ const tracksToSwap = validationResults.filter((result) => result.exists);
6208
+ if (tracksToSwap.length > 0) {
6209
+ const trackModes = /* @__PURE__ */ new Map();
6210
+ tracksToSwap.forEach(({ trackInfo }) => {
6211
+ const textTrack = trackInfo.trackElement.track;
6212
+ if (textTrack) {
6213
+ trackModes.set(trackInfo, {
6214
+ wasShowing: textTrack.mode === "showing",
6215
+ wasHidden: textTrack.mode === "hidden"
6216
+ });
6217
+ } else {
6218
+ trackModes.set(trackInfo, {
6219
+ wasShowing: false,
6220
+ wasHidden: false
6221
+ });
6222
+ }
6223
+ });
6224
+ const tracksToReadd = tracksToSwap.map(({ trackInfo }) => {
6225
+ const oldSrc = trackInfo.trackElement.getAttribute("src");
6226
+ const parent = trackInfo.trackElement.parentNode;
6227
+ const nextSibling = trackInfo.trackElement.nextSibling;
6228
+ const attributes = {};
6229
+ Array.from(trackInfo.trackElement.attributes).forEach((attr) => {
6230
+ attributes[attr.name] = attr.value;
6231
+ });
6232
+ return {
6233
+ trackInfo,
6234
+ oldSrc,
6235
+ parent,
6236
+ nextSibling,
6237
+ attributes
6238
+ };
6239
+ });
6240
+ tracksToReadd.forEach(({ trackInfo }) => {
6241
+ trackInfo.trackElement.remove();
6242
+ });
6243
+ this.element.load();
6244
+ setTimeout(() => {
6245
+ tracksToReadd.forEach(({ trackInfo, oldSrc, parent, nextSibling, attributes }) => {
6246
+ swappedTracksForTranscript.push(trackInfo);
6247
+ const newTrackElement = document.createElement("track");
6248
+ newTrackElement.setAttribute("src", trackInfo.describedSrc);
6249
+ Object.keys(attributes).forEach((attrName) => {
6250
+ if (attrName !== "src" && attrName !== "data-desc-src") {
6251
+ newTrackElement.setAttribute(attrName, attributes[attrName]);
6252
+ }
6253
+ });
6254
+ if (nextSibling && nextSibling.parentNode) {
6255
+ parent.insertBefore(newTrackElement, nextSibling);
6256
+ } else {
6257
+ parent.appendChild(newTrackElement);
6258
+ }
6259
+ trackInfo.trackElement = newTrackElement;
6260
+ });
6261
+ this.element.load();
6262
+ const setupNewTracks = () => {
6263
+ setTimeout(() => {
6264
+ swappedTracksForTranscript.forEach((trackInfo) => {
6265
+ const trackElement = trackInfo.trackElement;
6266
+ const newTextTrack = trackElement.track;
6267
+ if (newTextTrack) {
6268
+ const modeInfo = trackModes.get(trackInfo) || { wasShowing: false, wasHidden: false };
6269
+ newTextTrack.mode = "hidden";
6270
+ const restoreMode = () => {
6271
+ if (modeInfo.wasShowing) {
6272
+ newTextTrack.mode = "hidden";
6273
+ } else if (modeInfo.wasHidden) {
6274
+ newTextTrack.mode = "hidden";
6275
+ } else {
6276
+ newTextTrack.mode = "disabled";
6277
+ }
6278
+ };
6279
+ if (newTextTrack.readyState >= 2) {
6280
+ restoreMode();
6281
+ } else {
6282
+ newTextTrack.addEventListener("load", restoreMode, { once: true });
6283
+ newTextTrack.addEventListener("error", restoreMode, { once: true });
6284
+ }
6285
+ }
6286
+ });
6287
+ }, 300);
6288
+ };
6289
+ if (this.element.readyState >= 1) {
6290
+ setTimeout(setupNewTracks, 200);
6291
+ } else {
6292
+ this.element.addEventListener("loadedmetadata", setupNewTracks, { once: true });
6293
+ setTimeout(setupNewTracks, 2e3);
6294
+ }
6295
+ }, 100);
6296
+ }
6297
+ }
6298
+ const fallbackSourceElements = Array.from(this.element.querySelectorAll("source"));
6299
+ const hasSourceElementsWithDesc2 = fallbackSourceElements.some((el) => el.getAttribute("data-desc-src"));
6300
+ if (hasSourceElementsWithDesc2) {
6301
+ const fallbackSourcesToUpdate = [];
6302
+ fallbackSourceElements.forEach((sourceEl) => {
6303
+ const descSrcAttr = sourceEl.getAttribute("data-desc-src");
6304
+ const currentSrc = sourceEl.getAttribute("src");
6305
+ if (descSrcAttr) {
6306
+ const type = sourceEl.getAttribute("type");
6307
+ let origSrc = sourceEl.getAttribute("data-orig-src");
6308
+ if (!origSrc) {
6309
+ origSrc = currentSrc;
6310
+ }
6311
+ fallbackSourcesToUpdate.push({
6312
+ src: descSrcAttr,
6313
+ type,
6314
+ origSrc,
6315
+ descSrc: descSrcAttr
6316
+ });
6317
+ } else {
6318
+ const type = sourceEl.getAttribute("type");
6319
+ const src = sourceEl.getAttribute("src");
6320
+ fallbackSourcesToUpdate.push({
6321
+ src,
6322
+ type,
6323
+ origSrc: null,
6324
+ descSrc: null
6325
+ });
6326
+ }
6327
+ });
6328
+ fallbackSourceElements.forEach((sourceEl) => {
6329
+ sourceEl.remove();
6330
+ });
6331
+ fallbackSourcesToUpdate.forEach((sourceInfo) => {
6332
+ const newSource = document.createElement("source");
6333
+ newSource.setAttribute("src", sourceInfo.src);
6334
+ if (sourceInfo.type) {
6335
+ newSource.setAttribute("type", sourceInfo.type);
6336
+ }
6337
+ if (sourceInfo.origSrc) {
6338
+ newSource.setAttribute("data-orig-src", sourceInfo.origSrc);
6339
+ }
6340
+ if (sourceInfo.descSrc) {
6341
+ newSource.setAttribute("data-desc-src", sourceInfo.descSrc);
6342
+ }
6343
+ this.element.appendChild(newSource);
6344
+ });
6345
+ this.element.load();
6346
+ } else {
6347
+ this.element.src = this.audioDescriptionSrc;
6348
+ }
6349
+ }
5919
6350
  await new Promise((resolve) => {
5920
6351
  const onLoadedMetadata = () => {
5921
6352
  this.element.removeEventListener("loadedmetadata", onLoadedMetadata);
@@ -5923,10 +6354,183 @@ var Player = class extends EventEmitter {
5923
6354
  };
5924
6355
  this.element.addEventListener("loadedmetadata", onLoadedMetadata);
5925
6356
  });
6357
+ if (this.element.tagName === "VIDEO" && currentTime === 0 && !wasPlaying) {
6358
+ if (this.element.readyState >= 1) {
6359
+ this.element.currentTime = 1e-3;
6360
+ setTimeout(() => {
6361
+ this.element.currentTime = 0;
6362
+ }, 10);
6363
+ }
6364
+ }
5926
6365
  this.seek(currentTime);
5927
6366
  if (wasPlaying) {
5928
6367
  this.play();
5929
6368
  }
6369
+ if (swappedTracksForTranscript.length > 0 && this.captionManager) {
6370
+ const wasCaptionsEnabled = this.state.captionsEnabled;
6371
+ let currentTrackInfo = null;
6372
+ if (this.captionManager.currentTrack) {
6373
+ const currentTrackIndex = this.captionManager.tracks.findIndex((t) => t.track === this.captionManager.currentTrack.track);
6374
+ if (currentTrackIndex >= 0) {
6375
+ currentTrackInfo = {
6376
+ language: this.captionManager.tracks[currentTrackIndex].language,
6377
+ kind: this.captionManager.tracks[currentTrackIndex].kind
6378
+ };
6379
+ }
6380
+ }
6381
+ setTimeout(() => {
6382
+ this.captionManager.tracks = [];
6383
+ this.captionManager.loadTracks();
6384
+ if (wasCaptionsEnabled && currentTrackInfo && this.captionManager.tracks.length > 0) {
6385
+ const matchingTrackIndex = this.captionManager.tracks.findIndex(
6386
+ (t) => t.language === currentTrackInfo.language && t.kind === currentTrackInfo.kind
6387
+ );
6388
+ if (matchingTrackIndex >= 0) {
6389
+ this.captionManager.enable(matchingTrackIndex);
6390
+ } else if (this.captionManager.tracks.length > 0) {
6391
+ this.captionManager.enable(0);
6392
+ }
6393
+ }
6394
+ }, 600);
6395
+ }
6396
+ if (this.transcriptManager && this.transcriptManager.isVisible) {
6397
+ const swappedTracks = typeof swappedTracksForTranscript !== "undefined" ? swappedTracksForTranscript : [];
6398
+ if (swappedTracks.length > 0) {
6399
+ const onMetadataLoaded = () => {
6400
+ const allTextTracks = Array.from(this.element.textTracks);
6401
+ const freshTracks = swappedTracks.map((trackInfo) => {
6402
+ const trackEl = trackInfo.trackElement;
6403
+ const expectedSrc = trackEl.getAttribute("src");
6404
+ const srclang = trackEl.getAttribute("srclang");
6405
+ const kind = trackEl.getAttribute("kind");
6406
+ let foundTrack = allTextTracks.find((track) => trackEl.track === track);
6407
+ if (!foundTrack) {
6408
+ foundTrack = allTextTracks.find((track) => {
6409
+ if (track.language === srclang && (track.kind === kind || kind === "captions" && track.kind === "subtitles")) {
6410
+ const trackElementForTrack = Array.from(this.element.querySelectorAll("track")).find(
6411
+ (el) => el.track === track
6412
+ );
6413
+ if (trackElementForTrack) {
6414
+ const actualSrc = trackElementForTrack.getAttribute("src");
6415
+ if (actualSrc === expectedSrc) {
6416
+ return true;
6417
+ }
6418
+ }
6419
+ }
6420
+ return false;
6421
+ });
6422
+ }
6423
+ if (foundTrack) {
6424
+ const trackElement = Array.from(this.element.querySelectorAll("track")).find(
6425
+ (el) => el.track === foundTrack
6426
+ );
6427
+ if (trackElement && trackElement.getAttribute("src") !== expectedSrc) {
6428
+ return null;
6429
+ }
6430
+ }
6431
+ return foundTrack;
6432
+ }).filter(Boolean);
6433
+ if (freshTracks.length === 0) {
6434
+ setTimeout(() => {
6435
+ if (this.transcriptManager && this.transcriptManager.loadTranscriptData) {
6436
+ this.transcriptManager.loadTranscriptData();
6437
+ }
6438
+ }, 1e3);
6439
+ return;
6440
+ }
6441
+ freshTracks.forEach((track) => {
6442
+ if (track.mode === "disabled") {
6443
+ track.mode = "hidden";
6444
+ }
6445
+ });
6446
+ let loadedCount = 0;
6447
+ const checkLoaded = () => {
6448
+ loadedCount++;
6449
+ if (loadedCount >= freshTracks.length) {
6450
+ setTimeout(() => {
6451
+ if (this.transcriptManager && this.transcriptManager.loadTranscriptData) {
6452
+ const allTextTracks2 = Array.from(this.element.textTracks);
6453
+ const swappedTrackSrcs = swappedTracks.map((t) => t.describedSrc);
6454
+ const hasCorrectTracks = freshTracks.some((track) => {
6455
+ const trackEl = Array.from(this.element.querySelectorAll("track")).find(
6456
+ (el) => el.track === track
6457
+ );
6458
+ return trackEl && swappedTrackSrcs.includes(trackEl.getAttribute("src"));
6459
+ });
6460
+ if (hasCorrectTracks || freshTracks.length > 0) {
6461
+ this.transcriptManager.loadTranscriptData();
6462
+ }
6463
+ }
6464
+ }, 800);
6465
+ }
6466
+ };
6467
+ freshTracks.forEach((track) => {
6468
+ if (track.mode === "disabled") {
6469
+ track.mode = "hidden";
6470
+ }
6471
+ const trackElementForTrack = Array.from(this.element.querySelectorAll("track")).find(
6472
+ (el) => el.track === track
6473
+ );
6474
+ const actualSrc = trackElementForTrack ? trackElementForTrack.getAttribute("src") : null;
6475
+ const expectedTrackInfo = swappedTracks.find((t) => {
6476
+ const tEl = t.trackElement;
6477
+ return tEl && (tEl.track === track || tEl.getAttribute("srclang") === track.language && tEl.getAttribute("kind") === track.kind);
6478
+ });
6479
+ const expectedSrc = expectedTrackInfo ? expectedTrackInfo.describedSrc : null;
6480
+ if (expectedSrc && actualSrc && actualSrc !== expectedSrc) {
6481
+ checkLoaded();
6482
+ return;
6483
+ }
6484
+ if (track.readyState >= 2 && track.cues && track.cues.length > 0) {
6485
+ checkLoaded();
6486
+ } else {
6487
+ if (track.mode === "disabled") {
6488
+ track.mode = "hidden";
6489
+ }
6490
+ const onTrackLoad = () => {
6491
+ setTimeout(checkLoaded, 300);
6492
+ };
6493
+ if (track.readyState >= 2) {
6494
+ setTimeout(() => {
6495
+ if (track.cues && track.cues.length > 0) {
6496
+ checkLoaded();
6497
+ } else {
6498
+ track.addEventListener("load", onTrackLoad, { once: true });
6499
+ }
6500
+ }, 100);
6501
+ } else {
6502
+ track.addEventListener("load", onTrackLoad, { once: true });
6503
+ track.addEventListener("error", () => {
6504
+ checkLoaded();
6505
+ }, { once: true });
6506
+ }
6507
+ }
6508
+ });
6509
+ };
6510
+ const waitForTracks = () => {
6511
+ setTimeout(() => {
6512
+ if (this.element.readyState >= 1) {
6513
+ onMetadataLoaded();
6514
+ } else {
6515
+ this.element.addEventListener("loadedmetadata", onMetadataLoaded, { once: true });
6516
+ setTimeout(onMetadataLoaded, 2e3);
6517
+ }
6518
+ }, 500);
6519
+ };
6520
+ waitForTracks();
6521
+ setTimeout(() => {
6522
+ if (this.transcriptManager && this.transcriptManager.loadTranscriptData) {
6523
+ this.transcriptManager.loadTranscriptData();
6524
+ }
6525
+ }, 5e3);
6526
+ } else {
6527
+ setTimeout(() => {
6528
+ if (this.transcriptManager && this.transcriptManager.loadTranscriptData) {
6529
+ this.transcriptManager.loadTranscriptData();
6530
+ }
6531
+ }, 800);
6532
+ }
6533
+ }
5930
6534
  this.state.audioDescriptionEnabled = true;
5931
6535
  this.emit("audiodescriptionenabled");
5932
6536
  }
@@ -5936,7 +6540,64 @@ var Player = class extends EventEmitter {
5936
6540
  }
5937
6541
  const currentTime = this.state.currentTime;
5938
6542
  const wasPlaying = this.state.playing;
5939
- this.element.src = this.originalSrc;
6543
+ if (this.audioDescriptionCaptionTracks.length > 0) {
6544
+ this.audioDescriptionCaptionTracks.forEach((trackInfo) => {
6545
+ if (trackInfo.trackElement && trackInfo.originalTrackSrc) {
6546
+ trackInfo.trackElement.setAttribute("src", trackInfo.originalTrackSrc);
6547
+ }
6548
+ });
6549
+ }
6550
+ const allSourceElements = Array.from(this.element.querySelectorAll("source"));
6551
+ const hasSourceElementsToSwap = allSourceElements.some((el) => el.getAttribute("data-orig-src"));
6552
+ if (hasSourceElementsToSwap) {
6553
+ const sourcesToRestore = [];
6554
+ allSourceElements.forEach((sourceEl) => {
6555
+ const origSrcAttr = sourceEl.getAttribute("data-orig-src");
6556
+ const descSrcAttr = sourceEl.getAttribute("data-desc-src");
6557
+ if (origSrcAttr) {
6558
+ const type = sourceEl.getAttribute("type");
6559
+ sourcesToRestore.push({
6560
+ src: origSrcAttr,
6561
+ // Use original version
6562
+ type,
6563
+ origSrc: origSrcAttr,
6564
+ descSrc: descSrcAttr
6565
+ // Keep data-desc-src for future swaps
6566
+ });
6567
+ } else {
6568
+ const type = sourceEl.getAttribute("type");
6569
+ const src = sourceEl.getAttribute("src");
6570
+ sourcesToRestore.push({
6571
+ src,
6572
+ type,
6573
+ origSrc: null,
6574
+ descSrc: descSrcAttr
6575
+ });
6576
+ }
6577
+ });
6578
+ allSourceElements.forEach((sourceEl) => {
6579
+ sourceEl.remove();
6580
+ });
6581
+ sourcesToRestore.forEach((sourceInfo) => {
6582
+ const newSource = document.createElement("source");
6583
+ newSource.setAttribute("src", sourceInfo.src);
6584
+ if (sourceInfo.type) {
6585
+ newSource.setAttribute("type", sourceInfo.type);
6586
+ }
6587
+ if (sourceInfo.origSrc) {
6588
+ newSource.setAttribute("data-orig-src", sourceInfo.origSrc);
6589
+ }
6590
+ if (sourceInfo.descSrc) {
6591
+ newSource.setAttribute("data-desc-src", sourceInfo.descSrc);
6592
+ }
6593
+ this.element.appendChild(newSource);
6594
+ });
6595
+ this.element.load();
6596
+ } else {
6597
+ const originalSrcToUse = this.originalAudioDescriptionSource || this.originalSrc;
6598
+ this.element.src = originalSrcToUse;
6599
+ this.element.load();
6600
+ }
5940
6601
  await new Promise((resolve) => {
5941
6602
  const onLoadedMetadata = () => {
5942
6603
  this.element.removeEventListener("loadedmetadata", onLoadedMetadata);
@@ -5948,13 +6609,29 @@ var Player = class extends EventEmitter {
5948
6609
  if (wasPlaying) {
5949
6610
  this.play();
5950
6611
  }
6612
+ if (this.transcriptManager && this.transcriptManager.isVisible) {
6613
+ setTimeout(() => {
6614
+ if (this.transcriptManager && this.transcriptManager.loadTranscriptData) {
6615
+ this.transcriptManager.loadTranscriptData();
6616
+ }
6617
+ }, 500);
6618
+ }
5951
6619
  this.state.audioDescriptionEnabled = false;
5952
6620
  this.emit("audiodescriptiondisabled");
5953
6621
  }
5954
6622
  async toggleAudioDescription() {
5955
6623
  const textTracks = Array.from(this.element.textTracks || []);
5956
6624
  const descriptionTrack = textTracks.find((track) => track.kind === "descriptions");
5957
- if (descriptionTrack) {
6625
+ const hasAudioDescriptionSrc = this.audioDescriptionSrc || Array.from(this.element.querySelectorAll("source")).some((el) => el.getAttribute("data-desc-src"));
6626
+ if (descriptionTrack && hasAudioDescriptionSrc) {
6627
+ if (this.state.audioDescriptionEnabled) {
6628
+ descriptionTrack.mode = "hidden";
6629
+ await this.disableAudioDescription();
6630
+ } else {
6631
+ await this.enableAudioDescription();
6632
+ descriptionTrack.mode = "showing";
6633
+ }
6634
+ } else if (descriptionTrack) {
5958
6635
  if (descriptionTrack.mode === "showing") {
5959
6636
  descriptionTrack.mode = "hidden";
5960
6637
  this.state.audioDescriptionEnabled = false;
@@ -5964,7 +6641,7 @@ var Player = class extends EventEmitter {
5964
6641
  this.state.audioDescriptionEnabled = true;
5965
6642
  this.emit("audiodescriptionenabled");
5966
6643
  }
5967
- } else if (this.audioDescriptionSrc) {
6644
+ } else if (hasAudioDescriptionSrc) {
5968
6645
  if (this.state.audioDescriptionEnabled) {
5969
6646
  await this.disableAudioDescription();
5970
6647
  } else {