localhost でストリーミング

(2024-10-18)

IPTV は最近では規制が厳しく閲覧がかなり困難になってきました。

そもそも著作権の観点からグレーゾーンであり、規制強化の方向性は当然だと思われます。

ただ、昨今ではただでさえテレビ離れが進んでおりテレビを見なくなっているのに、ネットで地上波くらいはフリーに閲覧できるようにした方がテレビ局の利益になるのではないかと思います。

日本以外のほとんどの国では、インターネットで多くのチャンネルがフリーで閲覧できるようです。

でも、私は地上波で見るのはニュースくらいですけどね。

ts ファイルがあれば

IPTV の閲覧がほとんどできなければ ts ファイルをゲットすることはできないのですが、 実験的にある国のテレビ番組の ts ファイルをダウンロードしてローカルでストリーミングができないかトライしてみました。

python によるストリーミング

pythonによってストリーミングができます。

import os
import time
import shutil
# TSファイルの保存先フォルダ
source_dir = "ts_files" # ダウンロードされたTSファイルが保存されているディレクトリ
target_dir = "aaa" # コピー先のフォルダ
playlist_file = os.path.join(target_dir, "playlist.m3u8") # playlist.m3u8のパス
def get_ts_files_by_index(source_dir, start=0, limit=10):
"""指定されたフォルダから連番でTSファイルを取得する"""
ts_files = [f for f in os.listdir(source_dir) if f.endswith(".ts")]
ts_files.sort() # 名前順にソート (数字の順番に並ぶ)
# startからlimit個のファイルを取得
return ts_files[start:start + limit]
def copy_file(file, source_dir, target_dir):
"""1個のTSファイルをコピー"""
source_path = os.path.join(source_dir, file)
target_path = os.path.join(target_dir, file)
shutil.copy(source_path, target_path)
def generate_m3u8(files, target_dir, playlist_file, sequence):
"""playlist.m3u8ファイルを生成 (終了タグなし)"""
with open(playlist_file, "w") as f:
f.write("#EXTM3U\n")
f.write("#EXT-X-VERSION:3\n")
f.write("#EXT-X-TARGETDURATION:10\n")
f.write(f"#EXT-X-MEDIA-SEQUENCE:{sequence}\n") # シーケンス番号を更新
for ts_file in files:
f.write("#EXTINF:10.0,\n") # 各TSファイルの再生時間
f.write(f"{ts_file}\n")
# f.write("#EXT-X-ENDLIST\n") # 終了タグを削除
def update_playlist():
"""10秒ごとに1個ずつTSファイルを更新"""
start = 0 # 最初のTSファイルから開始
limit = 10 # 最初の10個を一度にコピーしてセット
sequence = 0 # シーケンス番号の初期化
# 最初に10個のTSファイルを1つずつコピーしてセットアップ
current_files = get_ts_files_by_index(source_dir, start=start, limit=limit)
for file in current_files:
copy_file(file, source_dir, target_dir)
# playlist.m3u8を生成
generate_m3u8(current_files, target_dir, playlist_file, sequence)
# 次のファイルから1個ずつ追加・削除を行う
start += limit
while True:
# 古いファイルを削除
oldest_file = current_files.pop(0) # 一番古いファイルをリストから取り出す
try:
os.remove(os.path.join(target_dir, oldest_file))
print(f"Deleted old file: {oldest_file}")
except Exception as e:
print(f"Error deleting file {oldest_file}: {e}")
# 新しいファイルを取得して追加
next_file = get_ts_files_by_index(source_dir, start=start, limit=1)
if not next_file:
print("No more files to process.")
break # ファイルがなくなったら終了
current_files.append(next_file[0]) # 新しいファイルをリストに追加
copy_file(next_file[0], source_dir, target_dir)
# シーケンス番号を1ずつ増やす
sequence += 1
# playlist.m3u8を再生成
generate_m3u8(current_files, target_dir, playlist_file, sequence)
print(f"Added new file: {next_file[0]}, playlist updated.")
# 次のファイルに進む
start += 1
# 10秒待機
time.sleep(10)
# メインの実行
if __name__ == "__main__":
# 最初にターゲットフォルダが存在しなければ作成
if not os.path.exists(target_dir):
os.makedirs(target_dir)
# プレイリストの更新を10秒間隔で実行
update_playlist()

ts_files に ts ファイルが多数あるとして、そこから aaa フォルダに最初は10個コピーしてplaylist.m3u8ファイルを作成します。

その後は、10 秒ごとに古い ts ファイルを 1 個削除・新しい ts ファイルを 1 個追加して、そのたびに playlist.m3u8 を作り直します。

この python を実行します。

python サーバーの起動。

python サーバーを起動します。

windows であれば Git Bash から、

python -m http.server 8000

で起動します。

html

以下のような hmtl を作成します。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HLS Video Player</title>
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
</head>
<body>
<video id="video" controls></video>
<script>
if (Hls.isSupported()) {
var video = document.getElementById('video');
var hls = new Hls();
hls.loadSource('http://localhost:8000/playlist.m3u8'); // ローカルサーバーのURL
hls.attachMedia(video);
hls.on(Hls.Events.MANIFEST_PARSED, function () {
video.play();
});
}
else if (video.canPlayType('application/vnd.apple.mpegurl')) {
video.src = 'http://localhost:8000/playlist.m3u8';
video.addEventListener('loadedmetadata', function () {
video.play();
});
}
</script>
</body>
</html>

この html を閲覧するとストリーミングが実行できていることが確認されます。