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ên | type | id | Câu trả lời |
|---|---|---|---|
catalog | loại của danh mục | mã danh mục trong manifest | { "metas": [ … ] } |
meta | loại của mục | mã mục lấy từ danh mục | { "meta": { … } } |
stream | loại của mục | mã video (phim lẻ: chính mã của phim; một tập: mã của tập; tv: mã kênh) | { "streams": [ … ] } |
subtitles | loại của mục | mã video | { "subtitles": [ … ] } |
addon_catalog | lấy từ addonCatalogs | lấy từ addonCatalogs | { "addons": [ … ] } |
- Chuỗi truy vấn (query string) trên đường dẫn manifest được giữ lại và gắn sau
.jsoncủa mọi yêu cầu. Phần đứng trước/manifest.jsoncũng được giữ nguyên; addon có cấu hình đặt thiết lập của người dùng ở đó, ví dụhttps://addon.example.com/eyJsYW5nIjoiZW4ifQ/manifest.json. - Máy chủ dùng SDK trả về 404
{"err":"not found"}cho tài nguyên không có và 500{"err":"handler error"}khi xử lý lỗi; chúng cũng có thể chuyển hướng bằng mã 307. Máy chủ tĩnh trả về 404 cho mọi tệp không tồn tại.
Mã hoá: các đoạn đường dẫn và extra
resource,typevàidđược mã hoá riêng từng phần giống hàmencodeURIComponentcủa JavaScript: mọi byte trừ chữ cái, chữ số và- _ . ! ~ * ' ( )đều thành%XX. Vì vậytt1234567:1:2được gửi đi thànhtt1234567%3A1%3A2.extralà các cặptên=giá-trịnối bằng&, mỗi tên và giá trị được mã hoá cùng cách:search=his%20girl&skip=100. Dấu cách là%20, không bao giờ là+; ký tự&hay=nằm trong giá trị thành%26hay%3D.- Extra cho phép nhiều giá trị thì lặp lại tên:
genre=Action&genre=Comedy. TS IPTV ghi extra theo thứ tự khai báo trong manifest,skipluôn ở cuối, và bỏ hẳn đoạn/{extra}khi không có extra nào.
Manifest
| Trường | Bắt buộc | Nghĩa |
|---|---|---|
id | có | 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. |
version | có | Chuỗi phiên bản, thường theo semver (1.0.0). |
name | có | Tên hiển thị. |
description | có (theo đặc tả) | Một hai câu mô tả. |
types | có | Loại nội dung: movie, series, channel, tv, hoặc chuỗi bất kỳ. |
resources | có | "catalog", "meta", "stream", "subtitles", "addon_catalog", hoặc đối tượng { "name": "stream", "types": ["movie"], "idPrefixes": ["ex_"] }. |
catalogs | có (có thể là []) | Danh sách danh mục (xem dưới). |
idPrefixes | không | Chỉ 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_"]. |
addonCatalogs | không | Danh sách các addon khác (type, id, name). |
behaviorHints | không | adult, p2p, configurable, configurationRequired, epgProvider, đều là giá trị đúng/sai. |
logo, background, contactEmail | không | Logo (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" }:
| Extra | Nghĩa |
|---|---|
search | Tì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. |
genre | Bộ 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. |
skip | Phâ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 | Ở đâu | Nghĩa |
|---|---|---|
id, type, name | cả hai | Bắt buộc. |
poster, posterShape | cả hai | Ảnh bìa; hình dạng poster (dọc, mặc định), square hoặc landscape. |
genres, releaseInfo, description, imdbRating | cả hai | Chữ hiển thị trên thẻ và trang chi tiết. |
background, logo, released, runtime, language, country, links | meta | Trường của trang chi tiết. released theo ISO 8601; runtime là chữ, ví dụ "92 min". |
videos | meta | Cá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.isLive | meta | Mở 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ường | Nghĩa |
|---|---|
url | Đường dẫn trực tiếp https (hoặc http): MP4, MKV, HLS .m3u8, DASH .mpd. |
externalUrl | Một trang web để mở trong trình duyệt. |
name | Nhã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.request | Header 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.bingeGroup | Luồng cùng nhóm được ưu tiên cho tập tiếp theo. |
behaviorHints.filename, videoSize | Tên tệp và dung lượng; giúp trình phát đoán định dạng. |
behaviorHints.countryWhitelist | Mã 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ủ)
- 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.
- Sửa
manifest.json:idmới (tên miền đảo ngược của một tên miền bạn quản lý),name,description,idPrefixesvà các danh mục của riêng bạn. - 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. - 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ếtstream/{type}/{videoId}.json. - Giữ mã và giá trị
extraan 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õ). - Thử trên máy: trong thư mục, chạy
npx http-server . --cors -c-1rồi thêmhttp://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 })
- Chạy
npm install, rồinpm start. SDK in ra đường dẫn manifest,http://127.0.0.1:7000/manifest.json. - 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ùnghttp://<địa chỉ LAN của máy tính>:7000/manifest.json. - Để 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
- HTTPS. Đặc tả yêu cầu HTTPS cho mọi địa chỉ trừ
127.0.0.1. TS IPTV vẫn nhậnhttp://, kèm cảnh báo “Addon này không dùng kết nối mã hoá”. - CORS. Đặc tả yêu cầu header
Access-Control-Allow-Origin: *trên mọi đường dẫn, kể cả/manifest.json. TS IPTV là ứng dụng cài đặt nên không cần, nhưng trình phát chạy trên web thì cần, vì vậy hãy thêm nó. - Header bộ nhớ đệm.
Cache-Control: public, max-age=600cho danh mục và chi tiết là mặc định hợp lý; giữ thời gian ngắn cho câu trả lời về luồng nếu đường dẫn có hạn dùng. - Loại nội dung. Gửi tệp
.jsonvớiapplication/json, và không chuyển hướng từ/tệp.jsonsang/tệp.json/.
| 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 Hosting | Thê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. |
| Netlify | Tệp _headers ở thư mục gốc, dòng đầu là /*, dòng sau là Access-Control-Allow-Origin: *. |
| Vercel | vercel.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.js | Bấ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
- Đ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).
- Dán đường dẫn manifest (kết thúc bằng
/manifest.json). Đường dẫn cài đặt dạngstremio://…/manifest.jsoncũng dùng được; TS IPTV tự đổi nó thànhhttps://, hoặchttp://với máy trong mạng nội bộ (localhost,127.0.0.1,10.x,192.168.x,172.16–31.x). - 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).
- Đọ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.
- 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ỗi | Biểu hiện | Cá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ĩnh | Không tìm thấy tệp thể loại hay tìm kiếm | Trì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ĩnh | Không tạo được tệp trên Windows, hoặc lỗi 404 | Dùng _ hoặc - trong mã. |
| Mỗi trang chỉ 20 mục | Ứng dụng khác dừng sau trang đầu | Trả 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 resources | Chi tiết hoặc luồng không bao giờ được yêu cầu | Khai 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 streams | Khô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 CORS | Chạy trong TS IPTV nhưng lỗi trên trình phát web | Thêm Access-Control-Allow-Origin: *. |
GitHub Pages thiếu .nojekyll | Mấ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ạn | Luồ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ăng | Android | iOS | Máy tính |
|---|---|---|---|
Luồng url: MP4, HLS qua HTTPS/HTTP | Hỗ trợ | Hỗ trợ | Hỗ trợ |
Luồng url: DASH .mpd không có DRM | Hỗ trợ | Hỗ trợ qua trình phát VLC tích hợp; chỉ gửi header User-Agent và Referer | Hỗ trợ |
Luồng url: MKV | Hỗ trợ | Có thể không phát được | Hỗ trợ |
proxyHeaders.request | Mọi header | Cố gắng tối đa | Chỉ User-Agent và Referer |
externalUrl | Mở 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à YouTube | Khô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ếp | Hỗ trợ | ||
configurable, configurationRequired | Hỗ trợ Qua trang cấu hình của addon trong trình duyệt. | ||
Gợi ý adult, p2p | Cả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ừ addon | Hỗ trợ | ||
Phụ đề, addon lịch phát sóng (epgProvider), danh sách addon (addon_catalog), tự phát tập tiếp theo | Chư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.