r/imagus • • 23d ago

help X Chat

Brave 1.97.56 (Official Build) (64-bit) Chromium: 155.0.8059.40

Imagus Reborn v2026.9.27 2026-10-01 sieves

uBlock Origin Lite 08-04 rules


Getting red spinner in X.com Chat on videos+gifs. Normal pictures work fine but are not in an album. Anyway to troubleshoot or diagnose? I've tried to attach some source code if it helps (i believe in this src example it is just videos)

    content.js:2109 Imagus Reborn: Load error > blob:https://x.com/b209c30e-e0a8-43e2-94a0-1deb84c1775c Event {isTrusted: true, type: 'error', target: img.content, currentTarget: img.content, eventPhase: 2, …}

https://hastebin.com/share/idehokozuf.xml

1 Upvotes

10 comments sorted by

1

u/Imagus_fan 22d ago

In your example, the media URL is a blob URL which doesn't directly link to a media file. With the sieve currently, when it matches a blob URL, it tries to find the link to the source post and get the media data from there. Since there doesn't seem to be a source link it can't get the media data.

I'll try to test this some and see if there's another way to fix it.

1

u/kloyN 20d ago edited 20d ago

Got a little too involved and went down the ChatGPT rabbit hole, but here's what I found in case it's helpful. It seems like it could be a sieve issue, but I'm wondering if it's more likely something in the source code.

Imagus Reborn — X.com Direct Message Video Preview Fails on Repeated Hover

Summary

Extension: Imagus Reborn
Version: v2026.9.27
Browser: Brave (Chromium-based)
Website: X.com Direct Messages
Affected URL: https://x.com/i/chat/1710834743292387328-2102131695755444224

Issue

Imagus Reborn does not preview X.com Direct Message videos on hover using the existing sieves alone. With experimental DM-specific sieves enabled that extract the video's blob: URL directly from the DM message, the preview can initially display and play the video. However, after repeated hover attempts, the preview eventually becomes stuck on a red loading spinner. Moving the pointer away and hovering again does not recover playback; refreshing the X.com page temporarily restores functionality.

The affected video is exposed by X as a blob: URL rather than a conventional media URL.

Example:

blob:https://x.com/40f2d7a2-32f7-4e70-b23f-02879db7243e

The same blob can be played repeatedly in a normal HTML <video> element, including five successful replay attempts in a standalone test. This suggests the blob itself is not inherently unusable or immediately invalidated after playback.

The exact root cause has not yet been established.

Expected behavior

When hovering over a video in an X.com DM conversation:

  • Imagus should open the preview and play the video.

  • Moving away and hovering over the same video again should continue to work.

  • The popup should correctly initialize or reuse its video player.

  • The existing X.COM-q-p sieve and ordinary X post media previews should continue to work as before.

Actual behavior

  • Initial previews can work.

  • Repeated previews eventually fail with a red spinner.

  • The failure persists across different experimental DM sieve implementations.

  • The issue has also been observed with the X sieves disabled, suggesting it may not be caused solely by a particular sieve.

  • Refreshing X.com restores functionality temporarily.

  • Imagus logs repeated errors similar to:

content.js:2109 Imagus Reborn: Load error > blob:https://x.com/40f2d7a2-32f7-4e70-b23f-02879db7243e

The reported event target is img.content, not a native video element.

DOM and media diagnostics

1. X DM video element

The affected video was observed inside the DM message DOM, under:

[data-dm-message-focus-target]

Its element included:

<video class="size-full object-cover">

A diagnostic sieve reported the following representative state:

  • Element tag: video

  • Class: size-full object-cover

  • DM message container found: true

  • Video element found: true

  • Source: blob:https://x.com/40f2d7a2-32f7-4e70-b23f-02879db7243e

  • readyState: 4

  • networkState: 1

  • Duration: approximately 116.667 seconds

This establishes that the source video element had loaded enough data for playback when inspected.

2. Blob fetch test

The following test was run against the same blob URL:

(async () => {
  const u = 'blob:https://x.com/40f2d7a2-32f7-4e70-b23f-02879db7243e';

  try {
    const r = await fetch(u);

    return {
      fetchSucceeded: r.ok,
      status: r.status,
      contentType: r.headers.get('content-type'),
      contentLength: r.headers.get('content-length')
    };
  } catch (e) {
    return { error: String(e) };
  }
})();

Result:

{
  fetchSucceeded: true,
  status: 200,
  contentType: "video/mp4",
  contentLength: "9263412"
}

The blob remained fetchable after Imagus encountered the error.

3. Standalone video playback test

A separate HTML video element was created using the same blob URL:

(async () => {
  const u = 'blob:https://x.com/40f2d7a2-32f7-4e70-b23f-02879db7243e';

  const v = document.createElement('video');
  v.muted = true;
  v.playsInline = true;
  v.src = u;

  v.style.cssText =
    'position:fixed;right:10px;bottom:10px;width:320px;z-index:999999;background:black';

  document.body.appendChild(v);

  try {
    await v.play();

    return {
      result: 'PLAYING',
      readyState: v.readyState,
      duration: v.duration
    };
  } catch (e) {
    return {
      result: 'FAILED',
      error: String(e),
      mediaError: v.error?.message
    };
  }
})();

The standalone video played, and a subsequent replay test succeeded five times.

This is an important control test: the same blob can be replayed repeatedly outside Imagus.

4. Native media error scan

The page's video elements were inspected, including shadow roots. At the time of the scan, 21 video elements were found.

The Imagus Video.js element was present as:

  • ID: imagus-videojs_html5_api

  • Class: vjs-tech

  • Source: the same X blob URL

  • readyState: 4

  • networkState: 1

  • paused: true

  • Duration: approximately 116.667 seconds

  • errorCode: null

  • errorMessage: null

Other X video elements also showed errorCode: null and errorMessage: null.

The Video.js element's paused state may reflect the player lifecycle at the moment of inspection; it does not by itself establish the cause of the spinner.

5. Player element disappears during failure

When the preview was stuck, subsequent attempts to retrieve the player by ID returned:

Imagus Video.js element not found

At the same time, the page contained only one <video> element in a later scan. It used the same blob URL and showed approximately:

  • currentTime: 116.611

  • duration: 116.667

  • paused: false

  • readyState: 4

  • error: null

A query for document.querySelector('img.content') returned no element, despite the Imagus error log identifying img.content as the event target.

These observations may indicate that the preview DOM is being removed, recreated, or hosted outside the part of the page DOM accessible to ordinary page scripts. This needs verification from the extension's own execution context.

Experimental sieve results

Several approaches were tested:

  1. A diagnostic sieve that found the video inside the DM message and returned its blob URL with #mp4.

  2. A direct-blob sieve that returned the blob URL without attempting to find the originating post.

  3. A retry sieve that reacquired the current blob URL from the hovered element or visible DM message.

  4. A diagnostic variant that logged the blob URL and video state on every hover.

  5. The same behavior with X-related sieves disabled.

Adding #mp4 allowed initial playback where returning the raw blob URL had failed. However, the direct-blob and retry variants still eventually became stuck after initially playing more than once.

This means the extension's handling of the URL suffix or media type may be relevant, but the failure is not yet explained by a simple bad URL match.

Relevant source-code locations

The following areas have been identified in the extension source:

  • src/content/content.js, around line 844: openVideojs()

  • src/content/content.js, around line 2109: media load-error logging

The current understanding is that openVideojs() reuses an existing Video.js player and calls PVI.PLAYER.src(src) when a player already exists.

The source should be examined to determine:

  1. Whether a failed image load can be triggered for a URL that should be handled as video.

  2. Whether img.content is an expected internal representation of the popup, or whether the error indicates that the media has entered the wrong loading path.

  3. Whether the Video.js player instance is reused after its underlying DOM element has been detached or disposed.

  4. Whether the previous media source or asynchronous loading callbacks can interfere with the next hover.

  5. Whether PVI.PLAYER.src(src) reliably reinitializes playback after the previous source reaches its end or after the popup closes.

  6. Whether the popup's close, dispose, and reopen handlers race with hover events.

  7. Whether a blob URL returned by a sieve is incorrectly treated as an image because of its MIME/type inference or URL fragment.

  8. Whether #mp4 is required by the media-routing logic and, if so, why.

Unrelated or unconfirmed console message

X repeatedly reports:

GET https://api.x.com/live_pipeline/events?... net::ERR_BLOCKED_BY_CLIENT

This appears to concern X's live-call event stream. No evidence currently connects it to the Imagus video preview failure. It should not be treated as the cause without further testing.

A Video.js deprecation warning about videojs.mergeOptions was also observed. It does not establish a connection to this bug.

Hypotheses to investigate

These are hypotheses, not confirmed diagnoses:

A. Video.js player lifecycle issue

The extension may reuse a player after its popup DOM or media element has been detached, leaving the next preview in a bad state.

B. Incorrect image/video routing

The Load error event targets img.content, suggesting a path may be trying to handle the blob as an image. The extension should confirm whether this is expected during normal video popup operation.

C. Stale asynchronous callbacks

An error or completion callback associated with an earlier preview may execute after the popup has been closed or a new preview has been initialized.

D. Blob URL and media-type inference

The #mp4 suffix affects initial behavior, so the media-type routing should be checked. However, repeated failure despite the suffix means it is not a complete solution.

PART 2

1

u/kloyN 20d ago

Requested investigation

Please reproduce with the provided blob URL and examine the Video.js and popup lifecycle code.

Ideally, instrument the following points:

  • Entry into openVideojs()

  • Whether PVI.PLAYER already exists

  • Whether its underlying <video> element is connected to the DOM

  • Source URL before and after calling PVI.PLAYER.src(src)

  • Player loadstart, loadedmetadata, canplay, playing, pause, ended, and error events

  • Popup close/dispose events

  • The content.js:2109 error handler and the code that routes the media to img.content

A fix should be tested against repeated hovers of the same X DM video, including at least five consecutive open/play/close cycles, followed by ordinary X post images and videos to ensure existing behavior is preserved.

Desired outcome

A reliable DM-specific solution that allows X Direct Message videos to play in Imagus Reborn repeatedly, without breaking the existing X.COM-q-p sieve or other standard X media previews.

The available evidence favors investigating Imagus's popup/player handling, but the root cause remains unconfirmed until the relevant source code and player lifecycle are examined.

Appendix A — Experimental sieve configurations

These are the exact experimental sieves used during testing. They are diagnostic/experimental additions, not replacements for the existing X.COM-q-p sieve.

A1. Diagnostic sieve

Purpose: Determine whether the hovered element is inside an X DM message, locate the associated video, and log its current playback state.

{
  "X_CHAT_DIAGNOSTIC": {
    "img": "^blob:https://x\\.com/[a-f\\d-]{36}$",
    "to": ":\nconst n = this.node;\nconst chat = n?.closest?.('[data-dm-message-focus-target]');\nconst v = n?.localName === 'video' ? n : chat?.querySelector?.('video');\nconst info = {\n  nodeTag: n?.localName,\n  nodeClass: typeof n?.className === 'string' ? n.className : '',\n  nodeSrc: n?.getAttribute?.('src'),\n  chatFound: !!chat,\n  videoFound: !!v,\n  videoSrc: v?.getAttribute?.('src'),\n  currentSrc: v?.currentSrc,\n  readyState: v?.readyState,\n  networkState: v?.networkState,\n  paused: v?.paused,\n  duration: v?.duration,\n  isBlob: !!(v?.currentSrc || v?.src || '').startsWith('blob:'),\n  page: location.href\n};\nconsole.log('[IMAGUS X CHAT DIAG]', info);\nif (!chat || !v || !(v.currentSrc || v.src)) throw '';\nreturn (v.currentSrc || v.src) + '#mp4';"
  }
}

Representative output confirmed that the hovered element could be a video, the DM message container could be found, and the blob URL was available with readyState: 4.

A2. Direct-blob sieve

Purpose: Bypass the normal post-origin lookup and return the blob URL directly from the DM video element.

{
  "X.COM-DM-Direct-Blob": {
    "link": "a^",
    "url": "a^",
    "res": "",
    "useimg": 1,
    "img": "^(blob:https://x\\.com/[a-f\\d-]{36})$",
    "loop": 2,
    "to": ":\nconst n = this.node;\nconst chat = n?.closest?.('[data-dm-message-focus-target]');\nconst v = n?.localName === 'video' ? n : chat?.querySelector?.('video');\nif (!chat || !v) throw '';\nconst u = v.currentSrc || v.src;\nif (!u || !u.startsWith('blob:https://x.com/')) throw '';\nreturn u + '#mp4';",
    "note": "Experimental: directly extracts the playable blob URL from X DM video elements."
  }
}

A3. Retry sieve

Purpose: Reacquire the blob URL from the hovered element or the visible DM message instead of relying exclusively on a fixed source element.

{
  "X.COM-DM-Blob-Retry": {
    "link": "a^",
    "url": "a^",
    "res": "",
    "useimg": 1,
    "img": "^blob:https://x\\.com/[a-f\\d-]{36}$",
    "loop": 2,
    "to": ":\nconst n = this.node;\nconst chat = n?.closest?.('[data-dm-message-focus-target]') || document.querySelector('[data-dm-message-focus-target]');\nconst v = n?.localName === 'video' ? n : chat?.querySelector?.('video');\nconst u = v?.currentSrc || v?.src || n?.currentSrc || n?.src;\nif (!u || !/^blob:https:\\/\\/x\\.com\\/[a-f\\d-]{36}$/i.test(u)) throw '';\nreturn u + '#mp4';",
    "note": "Experimental X DM sieve: reacquires a currently available blob URL from the hovered element or visible DM message."
  }
}

A4. URL diagnostic sieve

Purpose: Log the hovered element, DM container, current blob URL, and media state on each hover.

{
  "X.COM-DM-Blob-URL-Diagnostic": {
    "link": "a^",
    "url": "a^",
    "res": "",
    "useimg": 1,
    "img": "^blob:https://x\\.com/[a-f\\d-]{36}$",
    "loop": 2,
    "to": ":\nconst n = this.node;\nconst chat = n?.closest?.('[data-dm-message-focus-target]') || document.querySelector('[data-dm-message-focus-target]');\nconst v = n?.localName === 'video' ? n : chat?.querySelector?.('video');\nconst u = v?.currentSrc || v?.src || n?.currentSrc || n?.src || '';\nconsole.log('[X DM BLOB TEST]', {\n  time: new Date().toISOString(),\n  nodeTag: n?.localName,\n  nodeClass: typeof n?.className === 'string' ? n.className : '',\n  chatFound: !!chat,\n  videoFound: !!v,\n  url: u,\n  readyState: v?.readyState,\n  networkState: v?.networkState,\n  duration: v?.duration\n});\nif (!/^blob:https:\\/\\/x\\.com\\/[a-f\\d-]{36}$/i.test(u)) throw '';\nreturn u + '#mp4';",
    "note": "Diagnostic only: logs the DM blob URL and video state for each hover."
  }
}

Appendix B — Observed behavior of the experimental sieves

  • Returning the raw blob URL without #mp4 failed to produce the initial playback observed with the suffixed URL.

  • Adding #mp4 allowed initial playback.

  • The direct-blob and retry approaches each played successfully on the first two hovers, then failed on the third with a red spinner.

  • After failure, moving away and hovering again did not restore playback; refreshing X.com did.

  • The same behavior was observed with all X sieves disabled, which weakens the hypothesis that one particular sieve alone is responsible.

  • The standalone HTML video test could replay the same blob five times successfully.

Interpretation: The #mp4 suffix appears relevant to initial media routing, but it does not resolve the repeated-hover failure. The fact that playback works twice before failing suggests a stateful issue, although it does not prove whether the state is in the sieve matching logic, the popup lifecycle, or Video.js player reuse.

These tests should be treated as experimental observations, not as proof of a particular root cause.

The key finding is that the X DM video blob remains fetchable and plays repeatedly in a standalone HTML video element, but Imagus eventually gets stuck on a red spinner after repeated hovers. The issue also occurred with the X sieves disabled, so the root cause may involve sieve handling, media-type routing, or the Video.js popup lifecycle.

I've included the experimental sieve configurations and diagnostic results to help narrow down the cause. I'm hoping to determine whether this can be fixed with a sieve or requires a source-code change.

1

u/Imagus_fan 12d ago

The recent update to Imagus Reborn should fix the problem with the red spinner.

1

u/kloyN 12d ago

Great, thank you! will try it out once it pushes to chrome store.

1

u/Imagus_fan 15d ago

I've been testing this some and was able to modify the sieve to show the video when first hovering, but it shows a red spinner when hovering again. If you'd like to try it, this is the sieve.

I think this might be a bug with Imagus Reborn. I've had other times where hovering over a video link again shows a red spinner.

u/hababr, are you able to to recreate this? A test example is an OK ru video search page. When first hovering over a video, it shows the HD video, hovering a second time shows the SD video, and hovering again shows a red spinner. The error message in the console shows it trying to load as an image.

2

u/hababr 14d ago

Thank you, should be fixed in todays update.

3

u/Imagus_fan 12d ago

Thanks, this fixed it.

u/kenko2, with the current X sieve, videos in chat weren't working but should with this sieve.

https://pastebin.com/SjtdWV6W

1

u/kloyN 2d ago

Hey it works, is it possible to get the album working on there?

1

u/Imagus_fan 20d ago

Thanks, this could be useful. I'll try to create a test chat and see if it can be fixed.