mirror of
https://github.com/dirtydishes/dreamio.git
synced 2026-06-06 21:38:15 +00:00
capture opensubtitles text tracks
This commit is contained in:
parent
5fb7e6cc02
commit
28f1dc4f8e
4 changed files with 155 additions and 4 deletions
|
|
@ -22,3 +22,4 @@
|
||||||
{"id":"int-26b872a1","kind":"field_change","created_at":"2026-05-25T14:31:46.83464Z","actor":"dirtydishes","issue_id":"dreamio-ese","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Added subtitle-shaped fetch/XHR inspection diagnostics and validated the build."}}
|
{"id":"int-26b872a1","kind":"field_change","created_at":"2026-05-25T14:31:46.83464Z","actor":"dirtydishes","issue_id":"dreamio-ese","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Added subtitle-shaped fetch/XHR inspection diagnostics and validated the build."}}
|
||||||
{"id":"int-4e095d3f","kind":"field_change","created_at":"2026-05-25T14:38:21.968713Z","actor":"dirtydishes","issue_id":"dreamio-djc","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Auto-select the first discovered VLC subtitle track when playback is still disabled, while preserving manual caption choices."}}
|
{"id":"int-4e095d3f","kind":"field_change","created_at":"2026-05-25T14:38:21.968713Z","actor":"dirtydishes","issue_id":"dreamio-djc","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Auto-select the first discovered VLC subtitle track when playback is still disabled, while preserving manual caption choices."}}
|
||||||
{"id":"int-96629c65","kind":"field_change","created_at":"2026-05-25T14:45:38.521113Z","actor":"dirtydishes","issue_id":"dreamio-ppj","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Re-applied the auto-selected VLC subtitle track after stream discovery and playback state changes to harden rendering timing."}}
|
{"id":"int-96629c65","kind":"field_change","created_at":"2026-05-25T14:45:38.521113Z","actor":"dirtydishes","issue_id":"dreamio-ppj","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Re-applied the auto-selected VLC subtitle track after stream discovery and playback state changes to harden rendering timing."}}
|
||||||
|
{"id":"int-027cec57","kind":"field_change","created_at":"2026-05-25T14:51:44.599319Z","actor":"dirtydishes","issue_id":"dreamio-3xi","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Captured OpenSubtitles V3 subtitle URLs from browser track elements and textTracks so they can be forwarded to native playback."}}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
{"_type":"issue","id":"dreamio-8cz","title":"fix stremio external subtitle loading regression","description":"After adding late subtitle forwarding for native playback, Stremio external subtitle loading is failing. Investigate the injected bridge and native subtitle forwarding path, then adjust behavior so Stremio can still load external subtitles while native playback receives late candidates.","status":"closed","priority":0,"issue_type":"bug","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-05-25T11:05:42Z","created_by":"dirtydishes","updated_at":"2026-05-25T11:07:35Z","started_at":"2026-05-25T11:05:55Z","closed_at":"2026-05-25T11:07:35Z","close_reason":"Hardened subtitle bridge network observers so non-text Stremio subtitle loads are not touched, and made parser traversal deterministic for metadata preservation.","dependency_count":0,"dependent_count":0,"comment_count":0}
|
{"_type":"issue","id":"dreamio-8cz","title":"fix stremio external subtitle loading regression","description":"After adding late subtitle forwarding for native playback, Stremio external subtitle loading is failing. Investigate the injected bridge and native subtitle forwarding path, then adjust behavior so Stremio can still load external subtitles while native playback receives late candidates.","status":"closed","priority":0,"issue_type":"bug","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-05-25T11:05:42Z","created_by":"dirtydishes","updated_at":"2026-05-25T11:07:35Z","started_at":"2026-05-25T11:05:55Z","closed_at":"2026-05-25T11:07:35Z","close_reason":"Hardened subtitle bridge network observers so non-text Stremio subtitle loads are not touched, and made parser traversal deterministic for metadata preservation.","dependency_count":0,"dependent_count":0,"comment_count":0}
|
||||||
|
{"_type":"issue","id":"dreamio-3xi","title":"Capture browser text tracks for OpenSubtitles V3","description":"OpenSubtitles V3 subtitles can be attached to the Stremio web player as HTML track/textTrack entries rather than appearing in the initial stream candidate. Extend the web bridge to inspect track elements and textTracks so external subtitles can be forwarded to native playback.","status":"closed","priority":1,"issue_type":"bug","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-05-25T14:49:50Z","created_by":"dirtydishes","updated_at":"2026-05-25T14:51:45Z","started_at":"2026-05-25T14:49:52Z","closed_at":"2026-05-25T14:51:45Z","close_reason":"Captured OpenSubtitles V3 subtitle URLs from browser track elements and textTracks so they can be forwarded to native playback.","dependency_count":0,"dependent_count":0,"comment_count":0}
|
||||||
{"_type":"issue","id":"dreamio-ppj","title":"Reapply VLC embedded subtitle selection after track discovery","description":"Device logs show VLC eventually exposes and selects the embedded English SDH subtitle track, but subtitles still do not render. Investigate and harden the VLC selection timing so embedded tracks are selected after discovery is stable.","status":"closed","priority":1,"issue_type":"bug","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-05-25T14:44:08Z","created_by":"dirtydishes","updated_at":"2026-05-25T14:45:38Z","started_at":"2026-05-25T14:44:18Z","closed_at":"2026-05-25T14:45:38Z","close_reason":"Re-applied the auto-selected VLC subtitle track after stream discovery and playback state changes to harden rendering timing.","dependency_count":0,"dependent_count":0,"comment_count":0}
|
{"_type":"issue","id":"dreamio-ppj","title":"Reapply VLC embedded subtitle selection after track discovery","description":"Device logs show VLC eventually exposes and selects the embedded English SDH subtitle track, but subtitles still do not render. Investigate and harden the VLC selection timing so embedded tracks are selected after discovery is stable.","status":"closed","priority":1,"issue_type":"bug","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-05-25T14:44:08Z","created_by":"dirtydishes","updated_at":"2026-05-25T14:45:38Z","started_at":"2026-05-25T14:44:18Z","closed_at":"2026-05-25T14:45:38Z","close_reason":"Re-applied the auto-selected VLC subtitle track after stream discovery and playback state changes to harden rendering timing.","dependency_count":0,"dependent_count":0,"comment_count":0}
|
||||||
{"_type":"issue","id":"dreamio-djc","title":"Auto-select embedded VLC subtitle tracks","description":"VLC discovers embedded MKV subtitle tracks after playback starts, but Dreamio leaves subtitles disabled when no external candidates were provided. Add automatic selection for the first selectable VLC subtitle track while preserving manual caption choices.","status":"closed","priority":1,"issue_type":"bug","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-05-25T14:36:11Z","created_by":"dirtydishes","updated_at":"2026-05-25T14:38:22Z","started_at":"2026-05-25T14:36:17Z","closed_at":"2026-05-25T14:38:22Z","close_reason":"Auto-select the first discovered VLC subtitle track when playback is still disabled, while preserving manual caption choices.","dependency_count":0,"dependent_count":0,"comment_count":0}
|
{"_type":"issue","id":"dreamio-djc","title":"Auto-select embedded VLC subtitle tracks","description":"VLC discovers embedded MKV subtitle tracks after playback starts, but Dreamio leaves subtitles disabled when no external candidates were provided. Add automatic selection for the first selectable VLC subtitle track while preserving manual caption choices.","status":"closed","priority":1,"issue_type":"bug","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-05-25T14:36:11Z","created_by":"dirtydishes","updated_at":"2026-05-25T14:38:22Z","started_at":"2026-05-25T14:36:17Z","closed_at":"2026-05-25T14:38:22Z","close_reason":"Auto-select the first discovered VLC subtitle track when playback is still disabled, while preserving manual caption choices.","dependency_count":0,"dependent_count":0,"comment_count":0}
|
||||||
{"_type":"issue","id":"dreamio-ese","title":"Discover Stremio external subtitle payloads","description":"Extend and instrument the injected web subtitle discovery path so Stremio/OpenSubtitles addon responses can be captured when native playback only sees embedded VLC subtitle tracks.","status":"closed","priority":1,"issue_type":"bug","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-05-25T14:29:57Z","created_by":"dirtydishes","updated_at":"2026-05-25T14:31:47Z","started_at":"2026-05-25T14:30:03Z","closed_at":"2026-05-25T14:31:47Z","close_reason":"Added subtitle-shaped fetch/XHR inspection diagnostics and validated the build.","dependency_count":0,"dependent_count":0,"comment_count":0}
|
{"_type":"issue","id":"dreamio-ese","title":"Discover Stremio external subtitle payloads","description":"Extend and instrument the injected web subtitle discovery path so Stremio/OpenSubtitles addon responses can be captured when native playback only sees embedded VLC subtitle tracks.","status":"closed","priority":1,"issue_type":"bug","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-05-25T14:29:57Z","created_by":"dirtydishes","updated_at":"2026-05-25T14:31:47Z","started_at":"2026-05-25T14:30:03Z","closed_at":"2026-05-25T14:31:47Z","close_reason":"Added subtitle-shaped fetch/XHR inspection diagnostics and validated the build.","dependency_count":0,"dependent_count":0,"comment_count":0}
|
||||||
|
|
|
||||||
|
|
@ -199,6 +199,37 @@ final class DreamioWebViewController: UIViewController {
|
||||||
postSubtitleCandidates([candidate]);
|
postSubtitleCandidates([candidate]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const inspectTrack = (track) => {
|
||||||
|
if (!track) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (track instanceof HTMLTrackElement) {
|
||||||
|
addSubtitleCandidate({
|
||||||
|
url: track.src || track.getAttribute("src") || "",
|
||||||
|
label: track.label || track.srclang || "External Subtitle",
|
||||||
|
language: track.srclang || ""
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const source = track.src || track.url || "";
|
||||||
|
if (source) {
|
||||||
|
addSubtitleCandidate({
|
||||||
|
url: source,
|
||||||
|
label: track.label || track.language || track.kind || "External Subtitle",
|
||||||
|
language: track.language || ""
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const inspectTextTracks = (media) => {
|
||||||
|
try {
|
||||||
|
Array.from(media.textTracks || []).forEach(inspectTrack);
|
||||||
|
} catch (_) {}
|
||||||
|
try {
|
||||||
|
media.querySelectorAll("track").forEach(inspectTrack);
|
||||||
|
} catch (_) {}
|
||||||
|
};
|
||||||
|
|
||||||
const postSubtitleInspection = (source, url, beforeCount, afterCount, payloadLength) => {
|
const postSubtitleInspection = (source, url, beforeCount, afterCount, payloadLength) => {
|
||||||
if (afterCount > beforeCount) {
|
if (afterCount > beforeCount) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -307,11 +338,17 @@ final class DreamioWebViewController: UIViewController {
|
||||||
if (!node) {
|
if (!node) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (node instanceof HTMLTrackElement) {
|
||||||
|
inspectTrack(node);
|
||||||
|
}
|
||||||
if (node instanceof HTMLVideoElement || node instanceof HTMLSourceElement) {
|
if (node instanceof HTMLVideoElement || node instanceof HTMLSourceElement) {
|
||||||
postCandidate(node.currentSrc || node.src || node.getAttribute("src"), node);
|
postCandidate(node.currentSrc || node.src || node.getAttribute("src"), node);
|
||||||
}
|
}
|
||||||
if (node.querySelectorAll) {
|
if (node.querySelectorAll) {
|
||||||
node.querySelectorAll("video, source").forEach(inspectMedia);
|
node.querySelectorAll("video, source, track").forEach(inspectMedia);
|
||||||
|
}
|
||||||
|
if (node instanceof HTMLVideoElement) {
|
||||||
|
inspectTextTracks(node);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -337,10 +374,34 @@ final class DreamioWebViewController: UIViewController {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const trackSrcDescriptor = Object.getOwnPropertyDescriptor(HTMLTrackElement.prototype, "src");
|
||||||
|
if (trackSrcDescriptor && trackSrcDescriptor.set) {
|
||||||
|
Object.defineProperty(HTMLTrackElement.prototype, "src", {
|
||||||
|
get: trackSrcDescriptor.get,
|
||||||
|
set(value) {
|
||||||
|
addSubtitleCandidate({
|
||||||
|
url: value,
|
||||||
|
label: this.label || this.srclang || "External Subtitle",
|
||||||
|
language: this.srclang || ""
|
||||||
|
});
|
||||||
|
return trackSrcDescriptor.set.call(this, value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const originalSetAttribute = Element.prototype.setAttribute;
|
const originalSetAttribute = Element.prototype.setAttribute;
|
||||||
Element.prototype.setAttribute = function(name, value) {
|
Element.prototype.setAttribute = function(name, value) {
|
||||||
if (String(name).toLowerCase() === "src" && (this instanceof HTMLVideoElement || this instanceof HTMLSourceElement)) {
|
if (String(name).toLowerCase() === "src") {
|
||||||
postCandidate(value, this);
|
if (this instanceof HTMLVideoElement || this instanceof HTMLSourceElement) {
|
||||||
|
postCandidate(value, this);
|
||||||
|
}
|
||||||
|
if (this instanceof HTMLTrackElement) {
|
||||||
|
addSubtitleCandidate({
|
||||||
|
url: value,
|
||||||
|
label: this.label || this.srclang || "External Subtitle",
|
||||||
|
language: this.srclang || ""
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return originalSetAttribute.call(this, name, value);
|
return originalSetAttribute.call(this, name, value);
|
||||||
};
|
};
|
||||||
|
|
@ -349,9 +410,13 @@ final class DreamioWebViewController: UIViewController {
|
||||||
HTMLMediaElement.prototype.load = function() {
|
HTMLMediaElement.prototype.load = function() {
|
||||||
inspectMedia(this);
|
inspectMedia(this);
|
||||||
this.querySelectorAll("source").forEach(inspectMedia);
|
this.querySelectorAll("source").forEach(inspectMedia);
|
||||||
|
inspectTextTracks(this);
|
||||||
return originalLoad.call(this);
|
return originalLoad.call(this);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
document.addEventListener("addtrack", (event) => {
|
||||||
|
inspectTrack(event.track || event.target);
|
||||||
|
}, true);
|
||||||
document.addEventListener("loadedmetadata", (event) => inspectMedia(event.target), true);
|
document.addEventListener("loadedmetadata", (event) => inspectMedia(event.target), true);
|
||||||
document.addEventListener("error", (event) => inspectMedia(event.target), true);
|
document.addEventListener("error", (event) => inspectMedia(event.target), true);
|
||||||
new MutationObserver((mutations) => {
|
new MutationObserver((mutations) => {
|
||||||
|
|
@ -365,7 +430,7 @@ final class DreamioWebViewController: UIViewController {
|
||||||
childList: true,
|
childList: true,
|
||||||
subtree: true,
|
subtree: true,
|
||||||
attributes: true,
|
attributes: true,
|
||||||
attributeFilter: ["src"]
|
attributeFilter: ["src", "label", "srclang"]
|
||||||
});
|
});
|
||||||
|
|
||||||
inspectMedia(document);
|
inspectMedia(document);
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue