How To Have Zero AIOStreams Downtime Without Selfhosting

Recently I've seen a lot of posts about different AIO streams instances being down so I thought I would share how I get no downtime for myself and family, without selfhosting, and without running multiple instances at the same time putting unnessasary load on public instances.

TLDR: Create free cloudflare account, create worker, paste code and URLs, then add the cloudflare/manifest.json in any streaming app that supports addons.

Would love to hear your thoughts.

Part 1: Clone your config to multiple instances

You want the same AIOStreams setup on multiple instances so any of them can serve you.

  1. Configure AIOStreams fully on one instance.
  2. Go to save and Install, then export your configuration JSON.
  3. Go to other AIOstreams instances import that same JSON, create password and save.
  4. From each instance, grab its manifest URL (the .../manifest.json link). You'll paste these into the Worker in Part 2.

Note: If you update your AIOstreams config, you'll need to clone it to the other instances, and some updates require updating the URLs within the Cloudstream worker, AIOstreams should say if this is required.

Instances I use in order (can use more/others)

Part 2: Create & Use the Cloudflare Worker

  1. Make a free account at https://dash.cloudflare.com/
  2. In the dashboard sidebar, go to Workers & Pages → Start Building → Start with hello world
  3. Give it a name → Deploy.
  4. On the Worker's page, click Edit code (top right).
  5. Delete everything in the editor and paste the full script from below.
  6. Paste your manifest URLs from Part 1 into the INSTANCES list at the top one per line, inside the quotes, best/most-reliable first.
  7. Click Deploy.
  8. Hit the blue refresh/preview button and copy your Worker's URL — it'll look like https://your-name.your-subdomain.workers.dev.
  9. Paste that URL into your Streaming app.

Note: Ai coded the cloudflare worker script:

Edit: Updated to direct user to configuration page. Credit: u/beetlebatter

// YOUR INSTANCES (best / most-reliable FIRST) ────────
const INSTANCES = [
  " ",
  " ",
  " ",
  " "

// add as many instances as you want, one per line
];


//  TIMEOUTS (edit these) ──────────────────────────────
// How long a LIVE instance may take to finish scraping a /stream/ request:
const STREAM_TIMEOUT_MS = 15000;
// 15s  <-- main knob


// Max time to decide an instance is DOWN (checking manifest, not waiting for streams)
const PROBE_TIMEOUT_MS = 2000;
// 2s
// ──────────────────────────────────────────────────────────


const BASES = INSTANCES
  .map(u => u.trim().replace(/\/manifest\.json\/?$/i, "").replace(/\/+$/, ""))
  .filter(Boolean);


export default {
  async fetch(request) {
    const url = new URL(request.url);
    const path = url.pathname + url.search;


    if (request.method === "OPTIONS") return new Response(null, { headers: cors() });
    if (url.pathname === "/" || url.pathname === "")
      return new Response(landing(url.host, BASES.length),
        { headers: { "content-type": "text/html; charset=utf-8", ...cors() } });
    if (url.pathname === "/health") return health();

    // Redirect the browser to the actual live instance's /configure page,
    // instead of proxying that page's content through this worker.
    if (url.pathname === "/configure") {
      for (const base of BASES) {
        if (await probe(base)) {
          return Response.redirect(base + "/configure" + url.search, 302);
        }
      }
      return allDown("no instance available for /configure");
    }

    const method = request.method;
    const body = ["GET", "HEAD"].includes(method) ? undefined : request.body;
    const isStream = /\/stream\//.test(url.pathname);
    let lastError = "no instances configured";


    // Pass a good upstream response straight back, with CORS added.
    const finalize = (res) => {
      const headers = new Headers(res.headers);
      headers.delete("content-encoding");
      // prevent double-decompress corruption
      headers.delete("content-length");
      for (const [k, v] of Object.entries(cors())) headers.set(k, v);
      return new Response(res.body, { status: res.status, headers });
    };


    // One stream attempt. withProbe=true runs a concurrent liveness probe that
    // aborts the request early if the instance is down. Returns a Response or null.
    const tryStream = async (base, withProbe) => {
      const ctrl = new AbortController();
      let abortReason = null, settled = false;
      const timer = setTimeout(() => { abortReason = "timed out"; ctrl.abort(); }, STREAM_TIMEOUT_MS);
      if (withProbe) {
        probe(base).then(alive => {
          if (!alive && !settled) { abortReason = "probe says instance is down"; ctrl.abort(); }
        });
      }
      try {
        const res = await fetch(base + path, { method, body, redirect: "follow", signal: ctrl.signal });
        settled = true;
        // responding now -> probe can't abort us; slow body is safe
        clearTimeout(timer);
        if (res.status >= 500 || res.status === 429) { lastError = `instance returned ${res.status}`; return null; }
        return res;
      } catch (err) {
        clearTimeout(timer);
        lastError = abortReason || err.message;
        return null;
      }
    };


    if (isStream) {

      let res = await tryStream(BASES[0], true);
      if (res) return finalize(res);


      // 2) #1 failed -> probe ALL remaining instances AT ONCE, jump to first alive.
      const rest = BASES.slice(1);
      const alive = await Promise.all(rest.map(probe));
      for (let i = 0; i < rest.length; i++) {
        if (!alive[i]) continue;
        // skip dead ones instantly
        res = await tryStream(rest[i], false);
        // already confirmed alive this round
        if (res) return finalize(res);
      }
      return allDown(lastError);
    }


    for (const base of BASES) {
      const ctrl = new AbortController();
      const timer = setTimeout(() => ctrl.abort(), PROBE_TIMEOUT_MS);
      try {
        const res = await fetch(base + path, { method, body, redirect: "follow", signal: ctrl.signal });
        clearTimeout(timer);
        if (res.status >= 500 || res.status === 429) { lastError = `instance returned ${res.status}`; continue; }
        return finalize(res);
      } catch (err) {
        clearTimeout(timer);
        lastError = err.message;
        continue;
      }
    }
    return allDown(lastError);
  },
};



async function probe(base) {
  const ctrl = new AbortController();
  const t = setTimeout(() => ctrl.abort(), PROBE_TIMEOUT_MS);
  try {
    const r = await fetch(base + "/manifest.json", { redirect: "follow", signal: ctrl.signal });
    clearTimeout(t);
    return r.ok;
    // 2xx = alive
  } catch {
    clearTimeout(t);
    return false;
  }
}


function allDown(detail) {
  return new Response(JSON.stringify({ error: "All instances unavailable", detail }),
    { status: 502, headers: { "content-type": "application/json", ...cors() } });
}


function cors() {
  return {
    "Access-Control-Allow-Origin": "*",
    "Access-Control-Allow-Methods": "GET, HEAD, OPTIONS",
    "Access-Control-Allow-Headers": "*",
  };
}


async function health() {
  const results = await Promise.all(BASES.map(async (base) => {
    const start = Date.now();
    const ok = await probe(base);
    return { instance: base, ok, ms: Date.now() - start };
  }));
  return new Response(JSON.stringify({ instances: results }, null, 2),
    { headers: { "content-type": "application/json", ...cors() } });
}


function landing(host, count) {
  const manifest = `https://${host}/manifest.json`;
  return `<!doctype html><meta charset="utf-8"><title>AIOStreams failover proxy</title>
<body style="font-family:system-ui;max-width:640px;margin:60px auto;padding:0 16px;line-height:1.5">
<h1>✅ AIOStreams failover proxy is running</h1>
<p>${count} instance(s) configured. Install this URL in Stremio:</p>
<p><code style="background:#eee;padding:6px 10px;border-radius:6px">${manifest}</code></p>
<p><a href="/health">Check instance health →</a></p>
</body>`;
}
reddit.com
u/Titanspark2194 — 5 days ago

How To Have Zero AIOStreams Downtime Without Selfhosting

Recently I've seen a lot of posts about different AIO streams instances being down so I thought I would share how I get no downtime for myself and family, without selfhosting, and without running multiple instances at the same time putting unnessasary load on public instances.

TLDR: Create free cloudflare account, create worker, paste code and URLs, then add the cloudflare/manifest.json in Stremio.

Would love to hear your thoughts.

Part 1: Clone your config to multiple instances

You want the same AIOStreams setup on multiple instances so any of them can serve you.

  1. Configure AIOStreams fully on one instance.
  2. Go to save and Install, then export your configuration JSON.
  3. Go to other AIOstreams instances import that same JSON, create password and save.
  4. From each instance, grab its manifest URL (the .../manifest.json link). You'll paste these into the Worker in Part 2.

Note: If you update your AIOstreams config, you'll need to clone it to the other instances, and some updates require updating the URLs within the Cloudstream worker, AIOstreams should say if this is required.

Instances I use in order (can use more/others)

Part 2: Create & Use the Cloudflare Worker

  1. Make a free account at https://dash.cloudflare.com/
  2. In the dashboard sidebar, go to Workers & Pages → Start Building → Start with hello world
  3. Give it a name → Deploy.
  4. On the Worker's page, click Edit code (top right).
  5. Delete everything in the editor and paste the full script from below.
  6. Paste your manifest URLs from Part 1 into the INSTANCES list at the top one per line, inside the quotes, best/most-reliable first.
  7. Click Deploy.
  8. Hit the blue refresh/preview button and copy your Worker's URL — it'll look like https://your-name.your-subdomain.workers.dev.
  9. Paste that URL into your Streaming app.

Note: Ai coded the cloudflare worker script:

// YOUR INSTANCES (best / most-reliable FIRST) ────────
const INSTANCES = [
  " ",
  " ",
  " ",
  
// add as many instances as you want, one per line
];


//  TIMEOUTS (edit these) ──────────────────────────────
// How long a LIVE instance may take to finish scraping a /stream/ request:
const STREAM_TIMEOUT_MS = 15000;  
// 15s  <-- main knob


// Max time to decide an instance is DOWN (checking manifest, not waiting for streams)
const PROBE_TIMEOUT_MS = 2000;    
// 2s
// ──────────────────────────────────────────────────────────


/
const BASES = INSTANCES
  .map(u => u.trim().replace(/\/manifest\.json\/?$/i, "").replace(/\/+$/, ""))
  .filter(Boolean);


export default {
  async fetch(request) {
    const url = new URL(request.url);
    const path = url.pathname + url.search;


    if (request.method === "OPTIONS") return new Response(null, { headers: cors() });
    if (url.pathname === "/" || url.pathname === "")
      return new Response(landing(url.host, BASES.length),
        { headers: { "content-type": "text/html; charset=utf-8", ...cors() } });
    if (url.pathname === "/health") return health();


    const method = request.method;
    const body = ["GET", "HEAD"].includes(method) ? undefined : request.body;
    const isStream = /\/stream\//.test(url.pathname);
    let lastError = "no instances configured";


    
// Pass a good upstream response straight back, with CORS added.
    const finalize = (res) => {
      const headers = new Headers(res.headers);
      headers.delete("content-encoding"); 
// prevent double-decompress corruption
      headers.delete("content-length");
      for (const [k, v] of Object.entries(cors())) headers.set(k, v);
      return new Response(res.body, { status: res.status, headers });
    };


    
// One stream attempt. withProbe=true runs a concurrent liveness probe that
    
// aborts the request early if the instance is down. Returns a Response or null.
    const tryStream = async (base, withProbe) => {
      const ctrl = new AbortController();
      let abortReason = null, settled = false;
      const timer = setTimeout(() => { abortReason = "timed out"; ctrl.abort(); }, STREAM_TIMEOUT_MS);
      if (withProbe) {
        probe(base).then(alive => {
          if (!alive && !settled) { abortReason = "probe says instance is down"; ctrl.abort(); }
        });
      }
      try {
        const res = await fetch(base + path, { method, body, redirect: "follow", signal: ctrl.signal });
        settled = true;       
// responding now -> probe can't abort us; slow body is safe
        clearTimeout(timer);
        if (res.status >= 500 || res.status === 429) { lastError = `instance returned ${res.status}`; return null; }
        return res;
      } catch (err) {
        clearTimeout(timer);
        lastError = abortReason || err.message;
        return null;
      }
    };


    if (isStream) {
    
      let res = await tryStream(BASES[0], true);
      if (res) return finalize(res);


      
// 2) #1 failed -> probe ALL remaining instances AT ONCE, jump to first alive.
      const rest = BASES.slice(1);
      const alive = await Promise.all(rest.map(probe));
      for (let i = 0; i < rest.length; i++) {
        if (!alive[i]) continue;                 
// skip dead ones instantly
        res = await tryStream(rest[i], false);   
// already confirmed alive this round
        if (res) return finalize(res);
      }
      return allDown(lastError);
    }


    
    for (const base of BASES) {
      const ctrl = new AbortController();
      const timer = setTimeout(() => ctrl.abort(), PROBE_TIMEOUT_MS);
      try {
        const res = await fetch(base + path, { method, body, redirect: "follow", signal: ctrl.signal });
        clearTimeout(timer);
        if (res.status >= 500 || res.status === 429) { lastError = `instance returned ${res.status}`; continue; }
        return finalize(res);
      } catch (err) {
        clearTimeout(timer);
        lastError = err.message;
        continue;
      }
    }
    return allDown(lastError);
  },
};



async function probe(base) {
  const ctrl = new AbortController();
  const t = setTimeout(() => ctrl.abort(), PROBE_TIMEOUT_MS);
  try {
    const r = await fetch(base + "/manifest.json", { redirect: "follow", signal: ctrl.signal });
    clearTimeout(t);
    return r.ok; 
// 2xx = alive
  } catch {
    clearTimeout(t);
    return false;
  }
}


function allDown(detail) {
  return new Response(JSON.stringify({ error: "All instances unavailable", detail }),
    { status: 502, headers: { "content-type": "application/json", ...cors() } });
}


function cors() {
  return {
    "Access-Control-Allow-Origin": "*",
    "Access-Control-Allow-Methods": "GET, HEAD, OPTIONS",
    "Access-Control-Allow-Headers": "*",
  };
}


async function health() {
  const results = await Promise.all(BASES.map(async (base) => {
    const start = Date.now();
    const ok = await probe(base);
    return { instance: base, ok, ms: Date.now() - start };
  }));
  return new Response(JSON.stringify({ instances: results }, null, 2),
    { headers: { "content-type": "application/json", ...cors() } });
}


function landing(host, count) {
  const manifest = `https://${host}/manifest.json`;
  return `<!doctype html><meta charset="utf-8"><title>AIOStreams failover proxy</title>
<body style="font-family:system-ui;max-width:640px;margin:60px auto;padding:0 16px;line-height:1.5">
<h1>✅ AIOStreams failover proxy is running</h1>
<p>${count} instance(s) configured. Install this URL in Stremio:</p>
<p><code style="background:#eee;padding:6px 10px;border-radius:6px">${manifest}</code></p>
<p><a href="/health">Check instance health →</a></p>
</body>`;
}
reddit.com
u/Titanspark2194 — 5 days ago

How To Have Zero AIOStreams Downtime Without Selfhosting

Recently I've seen a lot of posts about different AIO streams instances being down so I thought I would share how I get no downtime for myself and family, without selfhosting, and without running multiple instances at the same time putting unnessasary load on public instances.

TLDR: Create free cloudflare account, create worker, paste code and URLs, give addon to streamer.

Would love to hear your thoughts.

Part 1: Clone your config to multiple instances

You want the same AIOStreams setup on multiple instances so any of them can serve you.

  1. Configure AIOStreams fully on one instance.
  2. Go to save and Install, then export your configuration JSON.
  3. Go to other AIOstreams instances import that same JSON, create password and save.
  4. From each instance, grab its manifest URL (the .../manifest.json link). You'll paste these into the Worker in Part 2.

Instances I use in order (can use more/others)

Part 2: Create & Use the Cloudflare Worker

  1. Make a free account at https://dash.cloudflare.com/
  2. In the dashboard sidebar, go to Workers & Pages → Start Building → Start with hello world
  3. Give it a name → Deploy.
  4. On the Worker's page, click Edit code (top right).
  5. Delete everything in the editor and paste the full script from below.
  6. Paste your manifest URLs from Part 1 into the INSTANCES list at the top one per line, inside the quotes, best/most-reliable first.
  7. Click Deploy.
  8. Hit the blue refresh/preview button and copy your Worker's URL — it'll look like https://your-name.your-subdomain.workers.dev.
  9. Paste that URL into your Streaming app.

Note: Ai coded the cloudflare worker script:

// YOUR INSTANCES (best / most-reliable FIRST) ────────
const INSTANCES = [
  " ",
  " ",
  " ",
  
// add as many instances as you want, one per line
];


//  TIMEOUTS (edit these) ──────────────────────────────
// How long a LIVE instance may take to finish scraping a /stream/ request:
const STREAM_TIMEOUT_MS = 15000;  
// 15s  <-- main knob


// Max time to decide an instance is DOWN (checking manifest, not waiting for streams)
const PROBE_TIMEOUT_MS = 2000;    
// 2s
// ──────────────────────────────────────────────────────────


/
const BASES = INSTANCES
  .map(u => u.trim().replace(/\/manifest\.json\/?$/i, "").replace(/\/+$/, ""))
  .filter(Boolean);


export default {
  async fetch(request) {
    const url = new URL(request.url);
    const path = url.pathname + url.search;


    if (request.method === "OPTIONS") return new Response(null, { headers: cors() });
    if (url.pathname === "/" || url.pathname === "")
      return new Response(landing(url.host, BASES.length),
        { headers: { "content-type": "text/html; charset=utf-8", ...cors() } });
    if (url.pathname === "/health") return health();


    const method = request.method;
    const body = ["GET", "HEAD"].includes(method) ? undefined : request.body;
    const isStream = /\/stream\//.test(url.pathname);
    let lastError = "no instances configured";


    
// Pass a good upstream response straight back, with CORS added.
    const finalize = (res) => {
      const headers = new Headers(res.headers);
      headers.delete("content-encoding"); 
// prevent double-decompress corruption
      headers.delete("content-length");
      for (const [k, v] of Object.entries(cors())) headers.set(k, v);
      return new Response(res.body, { status: res.status, headers });
    };


    
// One stream attempt. withProbe=true runs a concurrent liveness probe that
    
// aborts the request early if the instance is down. Returns a Response or null.
    const tryStream = async (base, withProbe) => {
      const ctrl = new AbortController();
      let abortReason = null, settled = false;
      const timer = setTimeout(() => { abortReason = "timed out"; ctrl.abort(); }, STREAM_TIMEOUT_MS);
      if (withProbe) {
        probe(base).then(alive => {
          if (!alive && !settled) { abortReason = "probe says instance is down"; ctrl.abort(); }
        });
      }
      try {
        const res = await fetch(base + path, { method, body, redirect: "follow", signal: ctrl.signal });
        settled = true;       
// responding now -> probe can't abort us; slow body is safe
        clearTimeout(timer);
        if (res.status >= 500 || res.status === 429) { lastError = `instance returned ${res.status}`; return null; }
        return res;
      } catch (err) {
        clearTimeout(timer);
        lastError = abortReason || err.message;
        return null;
      }
    };


    if (isStream) {
    
      let res = await tryStream(BASES[0], true);
      if (res) return finalize(res);


      
// 2) #1 failed -> probe ALL remaining instances AT ONCE, jump to first alive.
      const rest = BASES.slice(1);
      const alive = await Promise.all(rest.map(probe));
      for (let i = 0; i < rest.length; i++) {
        if (!alive[i]) continue;                 
// skip dead ones instantly
        res = await tryStream(rest[i], false);   
// already confirmed alive this round
        if (res) return finalize(res);
      }
      return allDown(lastError);
    }


    
    for (const base of BASES) {
      const ctrl = new AbortController();
      const timer = setTimeout(() => ctrl.abort(), PROBE_TIMEOUT_MS);
      try {
        const res = await fetch(base + path, { method, body, redirect: "follow", signal: ctrl.signal });
        clearTimeout(timer);
        if (res.status >= 500 || res.status === 429) { lastError = `instance returned ${res.status}`; continue; }
        return finalize(res);
      } catch (err) {
        clearTimeout(timer);
        lastError = err.message;
        continue;
      }
    }
    return allDown(lastError);
  },
};



async function probe(base) {
  const ctrl = new AbortController();
  const t = setTimeout(() => ctrl.abort(), PROBE_TIMEOUT_MS);
  try {
    const r = await fetch(base + "/manifest.json", { redirect: "follow", signal: ctrl.signal });
    clearTimeout(t);
    return r.ok; 
// 2xx = alive
  } catch {
    clearTimeout(t);
    return false;
  }
}


function allDown(detail) {
  return new Response(JSON.stringify({ error: "All instances unavailable", detail }),
    { status: 502, headers: { "content-type": "application/json", ...cors() } });
}


function cors() {
  return {
    "Access-Control-Allow-Origin": "*",
    "Access-Control-Allow-Methods": "GET, HEAD, OPTIONS",
    "Access-Control-Allow-Headers": "*",
  };
}


async function health() {
  const results = await Promise.all(BASES.map(async (base) => {
    const start = Date.now();
    const ok = await probe(base);
    return { instance: base, ok, ms: Date.now() - start };
  }));
  return new Response(JSON.stringify({ instances: results }, null, 2),
    { headers: { "content-type": "application/json", ...cors() } });
}


function landing(host, count) {
  const manifest = `https://${host}/manifest.json`;
  return `<!doctype html><meta charset="utf-8"><title>AIOStreams failover proxy</title>
<body style="font-family:system-ui;max-width:640px;margin:60px auto;padding:0 16px;line-height:1.5">
<h1>✅ AIOStreams failover proxy is running</h1>
<p>${count} instance(s) configured. Install this URL in Stremio:</p>
<p><code style="background:#eee;padding:6px 10px;border-radius:6px">${manifest}</code></p>
<p><a href="/health">Check instance health →</a></p>
</body>`;
}
reddit.com
u/Titanspark2194 — 6 days ago

3 Goals with Hy350 Max

I've seen the posts recently about rooted firmwares and ADB commands and debloating and have a few questions.

My goals are:

  1. Set custom launcher as default
  2. Set voice button on remote as speech to text instead of google assistant
  3. Debloat

I'd also like to keep the auto keystone and auto focus functionality.

When I got my HY350 Max I tried to do these things, but ran into various issues like accessibility setting turning itself off for the launcher and not being able to rebind the voice button. I tried ADB commands using ai but nothing worked.

What is the best option to achieve all these goals? With rooted firmware does auto keystone still work?

I really appreciate any help.

reddit.com
u/Titanspark2194 — 28 days ago

Fake Miyota 8215, though not a DG2813?

First image I think to be a clone/fake (claims Japanese) second image is genuine Japanese.

Planning my first build with Miyota 8215 and found 2 types. First image at about $35 Aud, second genuine at $55.

The clone/fake is very different from a Dg2813 and a genuine 2815, so what is it? I've looked and can't find info on it. Is it just another type of clone?

Thanks for any help.

u/Titanspark2194 — 2 months ago