TS IPTV

Addon tương thích Stremio

Addon là một dịch vụ web nhỏ, thậm chí chỉ là một thư mục tệp JSON tĩnh, trả lời vài loại yêu cầu HTTP bằng danh mục, thông tin chi tiết và đường dẫn luồng. Giao thức addon là giao thức mở, có tài liệu công khai; TS IPTV dùng được mọi addon tuân theo giao thức này và trả về đường dẫn video thông thường.

TS IPTV không có sẵn kênh nào và cũng không có sẵn addon nào. Ứng dụng không cài sẵn và không giới thiệu addon nào. Addon là dịch vụ của bên thứ ba do bạn tự thêm; bạn chịu trách nhiệm về quyền sử dụng mọi nội dung bạn xem qua chúng.

Giao thức này được tạo ra cho ứng dụng Stremio và được công bố dưới dạng đặc tả mở stremio-addon-sdk. TS IPTV không liên kết với Stremio và không được Stremio bảo trợ; cụm từ “tương thích Stremio” chỉ để mô tả giao thức. Mọi ví dụ dùng addon mẫu của chính TS IPTV trên tsiptv-8bdd6.web.app, phim thuộc phạm vi công cộng trên archive.org, một luồng thử nghiệm công khai, hoặc tên miền giả example.com.

Addon là gì

Mỗi addon được nhận diện bằng đường dẫn tới manifest của nó, một tệp JSON luôn kết thúc bằng /manifest.json. Manifest cho biết addon cung cấp gì: loại nội dung nào (movie, series, tv…), những danh mục nào, và những tài nguyên nào (danh sách, thông tin chi tiết, luồng, phụ đề). Trình phát dựng các đường dẫn tiếp theo từ địa chỉ của manifest và gửi yêu cầu HTTP GET thông thường. Mọi câu trả lời đều là JSON. Không có đăng nhập, phiên làm việc hay giao thức riêng, nên một addon có thể đơn giản chỉ là vài tệp trên một máy chủ web tĩnh.

Addon hữu ích khi bạn muốn đăng bộ sưu tập của riêng mình kèm ảnh bìa, mô tả, mùa và tập: ví dụ máy chủ media tại nhà, một dịch vụ có bản quyền do bạn vận hành, hoặc kho phim thuộc phạm vi công cộng.

Giao thức

Văn bản chuẩn là protocol.md và tài liệu API của SDK. Phần này tóm tắt những gì người viết addon cần biết.

Đường dẫn

Đường dẫn gốc (base URL) là đường dẫn manifest bỏ phần /manifest.json. Mọi yêu cầu khác đều dựng từ đó:

GET {base}/manifest.json
GET {base}/{resource}/{type}/{id}.json
GET {base}/{resource}/{type}/{id}/{extra}.json
Tài nguyêntypeidCâu trả lời
catalogloại của danh mụcmã danh mục trong manifest{ "metas": [ … ] }
metaloại của mụcmã mục lấy từ danh mục{ "meta": { … } }
streamloại của mụcmã video (phim lẻ: chính mã của phim; một tập: mã của tập; tv: mã kênh){ "streams": [ … ] }
subtitlesloại của mụcmã video{ "subtitles": [ … ] }
addon_cataloglấy từ addonCatalogslấy từ addonCatalogs{ "addons": [ … ] }

Mã hoá: các đoạn đường dẫn và extra

Manifest

TrườngBắt buộcNghĩa
idcóMã định danh kiểu tên miền đảo ngược, ví dụ com.example.myaddon. Thêm lại cùng mã nghĩa là cập nhật.
versioncóChuỗi phiên bản, thường theo semver (1.0.0).
namecóTên hiển thị.
descriptioncó (theo đặc tả)Một hai câu mô tả.
typescóLoại nội dung: movie, series, channel, tv, hoặc chuỗi bất kỳ.
resourcescó"catalog", "meta", "stream", "subtitles", "addon_catalog", hoặc đối tượng { "name": "stream", "types": ["movie"], "idPrefixes": ["ex_"] }.
catalogscó (có thể là [])Danh sách danh mục (xem dưới).
idPrefixeskhôngChỉ những mã bắt đầu bằng một trong các tiền tố này mới được gửi tới addon, ví dụ ["ex_"].
addonCatalogskhôngDanh sách các addon khác (type, id, name).
behaviorHintskhôngadult, p2p, configurable, configurationRequired, epgProvider, đều là giá trị đúng/sai.
logo, background, contactEmailkhôngLogo (PNG 256×256), ảnh nền, địa chỉ liên hệ.

Mỗi danh mục có dạng { "type", "id", "name", "extra": [ … ] }. Một id có thể dùng cho nhiều loại. Mỗi phần tử extra có dạng { "name", "isRequired", "options", "optionsLimit" }:

ExtraNghĩa
searchTìm kiếm tự do. isRequired: true tạo danh mục chỉ dùng để tìm, không bao giờ hiện thành một hàng.
genreBộ lọc; các giá trị lấy từ options. Thể loại bắt buộc sẽ bắt đầu ở giá trị đầu tiên.
skipPhân trang (xem dưới).
tên khácĐược phép; khai báo theo cùng cách.

Manifest kiểu cũ dùng danh sách chuỗi extraSupported/extraRequired và một danh sách genres riêng; TS IPTV vẫn đọc được, nhưng khi có cả hai thì extra được ưu tiên.

Phân trang

Mỗi trang danh mục chứa tối đa 100 mục. Trang đầu được yêu cầu không có skip; các trang sau dùng skip=100, skip=200, v.v. Theo đặc tả, trang có ít hơn 100 mục là trang cuối. TS IPTV dễ dãi hơn: nó yêu cầu trang tiếp theo với skip bằng số mục đã nhận, và dừng khi gặp trang rỗng, trang không có mục mới, hoặc câu trả lời lỗi ngay sau một trang ngắn (ví dụ 404 của máy chủ tĩnh). Chỉ khai báo skip khi danh mục của bạn có nhiều hơn một trang.

Mục trong danh mục và thông tin chi tiết

TrườngỞ đâuNghĩa
id, type, namecả haiBắt buộc.
poster, posterShapecả haiẢnh bìa; hình dạng poster (dọc, mặc định), square hoặc landscape.
genres, releaseInfo, description, imdbRatingcả haiChữ hiển thị trên thẻ và trang chi tiết.
background, logo, released, runtime, language, country, linksmetaTrường của trang chi tiết. released theo ISO 8601; runtime là chữ, ví dụ "92 min".
videosmetaCác tập của phim bộ (hoặc video của một kênh). Không có videos thì mục có đúng một video, mã video bằng mã mục.
behaviorHints.defaultVideoId, behaviorHints.isLivemetaMở thẳng video này; mục phát trực tiếp (tv luôn là trực tiếp).

Mỗi video có dạng { "id", "title", "released", "season", "episode", "thumbnail", "overview" }. Mùa 0 là các tập đặc biệt. Ngày released trong tương lai đánh dấu tập sắp ra mắt. Nếu một video tự mang mảng streams, chỉ những luồng đó được dùng cho nó.

Luồng

Mỗi đối tượng luồng có đúng một nguồn và vài nhãn:

TrườngNghĩa
urlĐường dẫn trực tiếp https (hoặc http): MP4, MKV, HLS .m3u8, DASH .mpd.
externalUrlMột trang web để mở trong trình duyệt.
nameNhãn ngắn, ví dụ chất lượng.
description (tên cũ: title)Nhãn dài hơn, có thể nhiều dòng.
behaviorHints.proxyHeaders.requestHeader HTTP cần gửi kèm mọi yêu cầu của luồng này, ví dụ { "User-Agent": "…", "Referer": "…" }. Đặc tả yêu cầu có kèm notWebReady: true.
behaviorHints.notWebReadyĐường dẫn không phát thẳng được trong trình duyệt web (không phải MP4, là http thường, hoặc cần header).
behaviorHints.bingeGroupLuồng cùng nhóm được ưu tiên cho tập tiếp theo.
behaviorHints.filename, videoSizeTên tệp và dung lượng; giúp trình phát đoán định dạng.
behaviorHints.countryWhitelistMã quốc gia ISO 3166-1 alpha-3 (chữ thường) nơi luồng hoạt động.

Đặc tả còn có các trường nguồn khác; TS IPTV không dùng chúng (xem TS IPTV phát được những gì). Hãy xếp luồng từ chất lượng cao nhất tới thấp nhất.

Phụ đề

GET {base}/subtitles/{type}/{videoId}.json, có thể kèm videoHash, videoSize và filename trong extra, trả về { "subtitles": [ { "id", "url", "lang", "label" } ] }. lang là mã ISO 639-2 như vie hoặc eng; tệp phụ đề là SRT hoặc VTT. TS IPTV hiện chưa dùng addon phụ đề.

Bộ nhớ đệm

Mọi câu trả lời đều có thể kèm cacheMaxAge, staleRevalidate và staleError (tính bằng giây). SDK đổi chúng thành header Cache-Control và vẫn giữ chúng trong JSON. TS IPTV ưu tiên Cache-Control, rồi đến các trường này, rồi đến giá trị mặc định của mình (danh mục 1 giờ, chi tiết 6 giờ, luồng 5 phút), và không bao giờ giữ câu trả lời về luồng quá 5 phút.

Loại và mã

Loại là chuỗi tự do; phổ biến là movie, series, channel và tv. Mã (id) là chuỗi không cần mang nghĩa. Hãy đặt cho mã một tiền tố riêng (ex_news, tspd_his_girl_friday) và khai báo nó trong idPrefixes, để trình phát chỉ hỏi addon của bạn về các mục của bạn. Mỗi tập có mã riêng, ví dụ tspd_superman_s1e1.

Ví dụ đầy đủ: addon mẫu

TS IPTV công bố một addon tĩnh nhỏ, Public Domain Sampler, làm ví dụ trực tiếp và dữ liệu kiểm thử. Nó có một phim lẻ (His Girl Friday, 1940), một loạt phim hoạt hình (Fleischer Superman, 1941–43), cả hai thuộc phạm vi công cộng trên archive.org, và một kênh trực tiếp phát luồng thử nghiệm công khai của Mux (Big Buck Bunny © Blender Foundation, CC BY 3.0). Đường dẫn manifest là https://tsiptv-8bdd6.web.app/examples/stremio-sampler/manifest.json.

Đây là toàn bộ các tệp của nó; mỗi tệp đúng bằng đường dẫn mà trình phát yêu cầu:

manifest.json
catalog/movie/tspd-movie.json
catalog/movie/tspd-movie/genre=Comedy.json
catalog/series/tspd-series.json
catalog/tv/tspd-tv.json
meta/movie/tspd_his_girl_friday.json
meta/series/tspd_superman.json
meta/tv/tspd_test_hls.json
stream/movie/tspd_his_girl_friday.json
stream/series/tspd_superman_s1e1.json
stream/tv/tspd_test_hls.json

manifest.json

{
  "id": "org.tsiptv.publicdomain.static",
  "version": "1.0.0",
  "name": "Public Domain Sampler (static)",
  "description": "Public-domain films and cartoons from archive.org, plus a public HLS test channel. Static JSON on GitHub Pages.",
  "resources": ["catalog", "meta", "stream"],
  "types": ["movie", "series", "tv"],
  "idPrefixes": ["tspd_"],
  "catalogs": [
    { "type": "movie",  "id": "tspd-movie",  "name": "Public Domain Movies",
      "extra": [ { "name": "genre", "isRequired": false, "options": ["Comedy"] } ] },
    { "type": "series", "id": "tspd-series", "name": "Public Domain Cartoons" },
    { "type": "tv",     "id": "tspd-tv",     "name": "Test Channels" }
  ],
  "behaviorHints": { "adult": false, "p2p": false }
}

Ba danh mục, mỗi loại một danh mục. Danh mục phim lẻ khai báo extra genre với đúng một giá trị, nên chỉ có một tệp extra: catalog/movie/tspd-movie/genre=Comedy.json (bản sao của danh sách không lọc). idPrefixes là tspd_, và mã dùng _ chứ không dùng :, vì mỗi mã sẽ thành một tên tệp.

catalog/movie/tspd-movie.json

{
  "metas": [
    { "id": "tspd_his_girl_friday", "type": "movie", "name": "His Girl Friday",
      "poster": "https://archive.org/services/img/his_girl_friday",
      "releaseInfo": "1940", "genres": ["Comedy"] }
  ]
}

Được yêu cầu tại …/catalog/movie/tspd-movie.json. Danh mục không khai báo skip, nên trang duy nhất này là toàn bộ danh mục và không có trang nào được yêu cầu thêm.

meta/series/tspd_superman.json

{
  "meta": {
    "id": "tspd_superman", "type": "series", "name": "Fleischer Superman (1941-43)",
    "poster": "https://archive.org/services/img/superman_the_mechanical_monsters",
    "releaseInfo": "1941-1943", "genres": ["Animation"],
    "description": "Fleischer Studios Superman cartoons, public domain.",
    "videos": [
      { "id": "tspd_superman_s1e1", "title": "The Mechanical Monsters",
        "season": 1, "episode": 1, "released": "1941-11-28T00:00:00.000Z",
        "thumbnail": "https://archive.org/services/img/superman_the_mechanical_monsters" }
    ]
  }
}

Phim bộ liệt kê các tập trong videos. Mã tập tspd_superman_s1e1 là mã mà yêu cầu luồng sử dụng.

stream/movie/tspd_his_girl_friday.json và stream/tv/tspd_test_hls.json

{
  "streams": [
    { "name": "archive.org", "description": "MP4 · 512kb",
      "url": "https://archive.org/download/his_girl_friday/his_girl_friday_512kb.mp4",
      "behaviorHints": { "filename": "his_girl_friday_512kb.mp4" } }
  ]
}
{
  "streams": [
    { "name": "HLS", "description": "Mux public test stream",
      "url": "https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8",
      "behaviorHints": { "notWebReady": true,
                         "proxyHeaders": { "request": { "User-Agent": "TSIPTV-Example/1.0" } } } }
  ]
}

Luồng của phim lẻ là một url MP4 trực tiếp kèm gợi ý filename. Luồng của kênh trực tiếp là HLS và yêu cầu header User-Agent qua proxyHeaders.request; TS IPTV gửi header này kèm mọi yêu cầu danh sách và đoạn video. Các tệp còn lại theo cùng mẫu: danh mục phim bộ, danh mục tv, chi tiết phim lẻ, chi tiết kênh, luồng của tập phim, tệp thể loại Comedy.

Tự tạo addon

Cách 1: tệp JSON tĩnh (không cần máy chủ)

  1. Tải các tệp mẫu ở trên về một thư mục, giữ nguyên cấu trúc thư mục.
  2. Sửa manifest.json: id mới (tên miền đảo ngược của một tên miền bạn quản lý), name, description, idPrefixes và các danh mục của riêng bạn.
  3. Với mỗi danh mục, viết catalog/{type}/{catalogId}.json. Thêm một tệp cho mỗi giá trị genre (catalog/{type}/{catalogId}/genre={giá-trị}.json) và, nếu có hơn 100 mục, …/skip=100.json, …/skip=200.json.
  4. Với mỗi mục, viết meta/{type}/{id}.json; với mỗi phim lẻ, tập phim hoặc kênh, viết stream/{type}/{videoId}.json.
  5. Giữ mã và giá trị extra an toàn cho URL: chữ cái, chữ số, _ và -. Kiểm tra từng tệp là JSON hợp lệ (VS Code báo lỗi ngay khi gõ).
  6. Thử trên máy: trong thư mục, chạy npx http-server . --cors -c-1 rồi thêm http://127.0.0.1:8080/manifest.json (trình giả lập Android: http://10.0.2.2:8080/manifest.json).

Giới hạn của addon tĩnh: không có tìm kiếm tự do search (vì không thể tạo sẵn mọi truy vấn), mỗi thể loại và mỗi trang là một tệp, và không có : trong mã (máy chủ sẽ tìm một tên tệp chứa :, điều Windows và một số máy chủ không cho phép).

Cách 2: SDK cho Node.js

Với SDK chính thức (Node.js 12 trở lên), bạn viết các hàm xử lý thay vì tệp, nhờ đó có tìm kiếm, danh mục lớn và câu trả lời được tính toán. serveHTTP tự thêm header CORS, và đổi các giá trị cacheMaxAge, staleRevalidate, staleError mà hàm xử lý trả về thành header Cache-Control.

package.json:

{
  "name": "my-publicdomain-addon",
  "version": "1.0.0",
  "main": "addon.js",
  "scripts": { "start": "node addon.js" },
  "dependencies": { "stremio-addon-sdk": "^1.6.10" }
}

addon.js (addon mẫu, có tìm kiếm, lọc thể loại và phân trang):

const { addonBuilder, serveHTTP } = require('stremio-addon-sdk')

const ITEMS = [
  { id: 'tspd_his_girl_friday', type: 'movie', name: 'His Girl Friday',
    releaseInfo: '1940', genres: ['Comedy'],
    poster: 'https://archive.org/services/img/his_girl_friday',
    streams: [{ name: 'archive.org', description: 'MP4 512kb',
      url: 'https://archive.org/download/his_girl_friday/his_girl_friday_512kb.mp4',
      behaviorHints: { filename: 'his_girl_friday_512kb.mp4' } }] },
  { id: 'tspd_superman', type: 'series', name: 'Fleischer Superman (1941-43)',
    releaseInfo: '1941-1943', genres: ['Animation'],
    poster: 'https://archive.org/services/img/superman_the_mechanical_monsters',
    videos: [{ id: 'tspd_superman_s1e1', title: 'The Mechanical Monsters',
      season: 1, episode: 1, released: '1941-11-28T00:00:00.000Z',
      streams: [{ name: 'archive.org', description: 'MP4 512kb',
        url: 'https://archive.org/download/superman_the_mechanical_monsters/superman_the_mechanical_monsters_512kb.mp4' }] }] },
  { id: 'tspd_test_hls', type: 'tv', name: 'HLS Test Channel',
    posterShape: 'square', poster: 'https://archive.org/services/img/his_girl_friday',
    streams: [{ name: 'HLS', description: 'Mux public test stream',
      url: 'https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8',
      behaviorHints: { notWebReady: true,
        proxyHeaders: { request: { 'User-Agent': 'TSIPTV-Example/1.0' } } } }] }
]
const PAGE = 100

const builder = new addonBuilder({
  id: 'org.example.publicdomain', version: '1.0.0', name: 'My Public Domain Addon',
  description: 'Public-domain films and cartoons, plus a public HLS test channel.',
  resources: ['catalog', 'meta', 'stream'], types: ['movie', 'series', 'tv'],
  idPrefixes: ['tspd_'],
  catalogs: ['movie', 'series', 'tv'].map(type => ({
    type, id: 'tspd-' + type, name: 'Public Domain ' + type,
    extra: [{ name: 'search' }, { name: 'genre', options: ['Animation', 'Comedy'] }, { name: 'skip' }]
  })),
  behaviorHints: { adult: false, p2p: false }
})

const preview = i => ({ id: i.id, type: i.type, name: i.name, poster: i.poster,
  posterShape: i.posterShape, genres: i.genres, releaseInfo: i.releaseInfo })

builder.defineCatalogHandler(({ type, id, extra }) => {
  let list = ITEMS.filter(i => i.type === type && id === 'tspd-' + type)
  if (extra.genre) list = list.filter(i => (i.genres || []).includes(extra.genre))
  if (extra.search) list = list.filter(i => i.name.toLowerCase().includes(extra.search.toLowerCase()))
  const skip = parseInt(extra.skip || '0', 10) || 0
  return Promise.resolve({ metas: list.slice(skip, skip + PAGE).map(preview), cacheMaxAge: 3600 })
})

builder.defineMetaHandler(({ type, id }) => {
  const i = ITEMS.find(x => x.id === id && x.type === type)
  if (!i) return Promise.resolve({ meta: null })
  const meta = preview(i)
  if (i.videos) meta.videos = i.videos.map(({ streams, ...v }) => v)
  return Promise.resolve({ meta, cacheMaxAge: 3600 })
})

builder.defineStreamHandler(({ type, id }) => {
  for (const i of ITEMS) {
    if (i.id === id && i.streams) return Promise.resolve({ streams: i.streams, cacheMaxAge: 600 })
    const v = (i.videos || []).find(v => v.id === id)
    if (v) return Promise.resolve({ streams: v.streams, cacheMaxAge: 600 })
  }
  return Promise.resolve({ streams: [] })
})

serveHTTP(builder.getInterface(), { port: process.env.PORT || 7000 })
  1. Chạy npm install, rồi npm start. SDK in ra đường dẫn manifest, http://127.0.0.1:7000/manifest.json.
  2. Thêm đường dẫn đó vào TS IPTV trên cùng máy tính; từ trình giả lập Android dùng http://10.0.2.2:7000/manifest.json; từ điện thoại hoặc TV trong cùng mạng dùng http://<địa chỉ LAN của máy tính>:7000/manifest.json.
  3. Để công bố, triển khai lên bất kỳ dịch vụ lưu trữ Node.js nào có địa chỉ HTTPS, rồi dùng https://<máy chủ của bạn>/manifest.json.

SDK cũng có thể tạo trang cấu hình (config trong manifest) và gắn addon vào một ứng dụng Express có sẵn; xem README của SDK.

Đưa addon lên mạng

Nơi lưu trữCần làm gì
GitHub PagesĐẩy cây thư mục lên một kho mã và bật Pages. Thêm một tệp rỗng .nojekyll ở thư mục gốc để tệp được phục vụ nguyên vẹn. Pages đã gửi sẵn Access-Control-Allow-Origin: *. Manifest: https://<user>.github.io/<repo>/manifest.json.
Firebase HostingThêm một quy tắc header trong firebase.json: {"source": "**/*.json", "headers": [{"key": "Access-Control-Allow-Origin", "value": "*"}]}. Addon mẫu của TS IPTV được lưu trữ theo cách này.
NetlifyTệp _headers ở thư mục gốc, dòng đầu là /*, dòng sau là Access-Control-Allow-Origin: *.
Vercelvercel.json: {"headers": [{"source": "/(.*)", "headers": [{"key": "Access-Control-Allow-Origin", "value": "*"}]}]}.
Máy chủ web bất kỳPhục vụ thư mục như tệp tĩnh và thêm header CORS, ví dụ với nginx: add_header Access-Control-Allow-Origin *;
SDK Node.jsBất kỳ dịch vụ Node.js nào có HTTPS; serveHTTP tự đặt header CORS; Cache-Control lấy từ cacheMaxAge mà hàm xử lý trả về.

Trang blob/ của GitHub hay trang chia sẻ tệp không phải là addon: đường dẫn manifest phải trả về chính nội dung JSON.

Thêm vào TS IPTV

  1. Điện thoại, máy tính bảng, iOS và máy tính: Hồ sơ → Addon → Thêm addon. Android TV: Cài đặt → Addon → Thêm addon (nhập đường dẫn bằng bàn phím trên màn hình).
  2. Dán đường dẫn manifest (kết thúc bằng /manifest.json). Đường dẫn cài đặt dạng stremio://…/manifest.json cũng dùng được; TS IPTV tự đổi nó thành https://, hoặc http:// với máy trong mạng nội bộ (localhost, 127.0.0.1, 10.x, 192.168.x, 172.16–31.x).
  3. Chọn Tiếp tục. Màn hình xem trước cho biết tên, phiên bản, máy chủ, loại nội dung, số danh mục, addon có cung cấp luồng hay không, và các cảnh báo (không mã hoá, ngang hàng P2P, nội dung người lớn).
  4. Đọc và đồng ý với thông báo (“Addon là dịch vụ của bên thứ ba, không do TS IPTV vận hành…”), rồi chọn Thêm.
  5. Mục Khám phá xuất hiện: trên điện thoại ở giữa Trang chủ và Lịch sử, trên TV ở đầu thanh bên của Trang chủ. Mỗi danh mục là một hàng; mở một nội dung và chọn một luồng để phát.

Nếu manifest có configurationRequired, TS IPTV chưa thêm ngay: chọn Cấu hình để mở trang /configure của addon trong trình duyệt (trên TV, địa chỉ được hiện dưới dạng chữ), hoàn tất ở đó rồi dán đường dẫn nó cung cấp. Quản lý addon (bật, tắt, sắp xếp, cập nhật, gỡ) ngay trên màn hình Addon. Đường dẫn addon có thể chứa thiết lập cá nhân, nên TS IPTV lưu chúng ở dạng mã hoá và chỉ hiển thị tên máy chủ.

Lỗi thường gặp

LỗiBiểu hiệnCách sửa
Đường dẫn không kết thúc bằng /manifest.json“Hãy nhập đường dẫn manifest của addon. Đường dẫn kết thúc bằng /manifest.json.”Dùng đường dẫn manifest, không phải trang web của addon.
Manifest thiếu trường (id, name, version, types, resources)“Đường dẫn này không trả về manifest addon hợp lệ.”Thêm trường còn thiếu; kiểm tra tệp là JSON hợp lệ.
Dùng + thay cho %20 trong tên tệp tĩnhKhông tìm thấy tệp thể loại hay tìm kiếmTrình phát gửi %20; chỉ đặt tên tệp bằng giá trị an toàn cho URL.
Có : trong mã của addon tĩnhKhông tạo được tệp trên Windows, hoặc lỗi 404Dùng _ hoặc - trong mã.
Mỗi trang chỉ 20 mụcỨng dụng khác dừng sau trang đầuTrả về 100 mục mỗi trang; chỉ trang cuối được ngắn hơn.
idPrefixes không khớp mã, hoặc thiếu "stream" trong resourcesChi tiết hoặc luồng không bao giờ được yêu cầuKhai báo mọi tài nguyên bạn phục vụ và một tiền tố chung cho mọi mã.
Video tự mang streamsKhông addon nào khác được hỏi về video đóChỉ dùng luồng gắn sẵn khi đó là những luồng duy nhất.
configurationRequired: true“Addon này cần được cấu hình trước.”Cấu hình trong trình duyệt rồi dán đường dẫn đã cấu hình.
Đường dẫn trên 127.0.0.1:11470“Địa chỉ này thuộc máy chủ cục bộ của ứng dụng Stremio…”Máy chủ đó thuộc một ứng dụng khác, không phải addon.
Addon kiểu cũ /stremio/v1“Đây là addon kiểu cũ, TS IPTV không dùng được.”Chỉ giao thức HTTP hiện tại được hỗ trợ.
Addon chỉ có nguồn khác url“Không tìm thấy luồng phát được cho nội dung này.”TS IPTV chỉ phát luồng url; xem bên dưới.
Không có header CORSChạy trong TS IPTV nhưng lỗi trên trình phát webThêm Access-Control-Allow-Origin: *.
GitHub Pages thiếu .nojekyllMất các tệp bắt đầu bằng _Thêm tệp rỗng .nojekyll.
Lưu đệm lâu đường dẫn luồng có chữ ký hoặc có hạnLuồng hỏng sau một thời gianĐặt cacheMaxAge ngắn cho câu trả lời về luồng.

TS IPTV phát được những gì

Tính năngAndroidiOSMáy tính
Luồng url: MP4, HLS qua HTTPS/HTTPHỗ trợHỗ trợHỗ trợ
Luồng url: DASH .mpd không có DRMHỗ trợHỗ trợ qua trình phát VLC tích hợp; chỉ gửi header User-Agent và RefererHỗ trợ
Luồng url: MKVHỗ trợCó thể không phát đượcHỗ trợ
proxyHeaders.requestMọi headerCố gắng tối đaChỉ User-Agent và Referer
externalUrlMở trong trình duyệt sau khi bạn xác nhận; trên TV không có trình duyệt, đường dẫn được hiện dưới dạng chữ. Liên kết trang stremio:///… mở màn hình tương ứng của TS IPTV.
Luồng torrent, Usenet, tệp nén và YouTubeKhông hỗ trợ
Danh mục, lọc thể loại, tìm kiếm, phân trang, phim bộ có mùa, mục tv trực tiếpHỗ trợ
configurable, configurationRequiredHỗ trợ Qua trang cấu hình của addon trong trình duyệt.
Gợi ý adult, p2pCảnh báo khi thêm; addon người lớn cần xác nhận đủ 18 tuổi và không xuất hiện trong các hàng của Khám phá hay trong tìm kiếm.
Xem tiếp và phát tiếp phim lẻ, tập phim từ addonHỗ trợ
Phụ đề, addon lịch phát sóng (epgProvider), danh sách addon (addon_catalog), tự phát tập tiếp theoChưa có

TS IPTV không có addon cài sẵn và không gợi ý addon nào. Addon chỉ bị tắt từ xa khi có yêu cầu gỡ bỏ bắt buộc.