Skip to content

Instantly share code, notes, and snippets.

@eggplants
Created August 16, 2024 19:52
Show Gist options
  • Save eggplants/ca989cea260d03747f0e2a7fcec29fec to your computer and use it in GitHub Desktop.
Save eggplants/ca989cea260d03747f0e2a7fcec29fec to your computer and use it in GitHub Desktop.
Convert mirakurun / mirakc json file of channels into m3u8 playlist file.
"""Convert mirakurun / mirakc json file of channels into m3u8 playlist file."""
from __future__ import annotations
import argparse
import json
import re
import sys
from pathlib import Path
from textwrap import dedent
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from collections.abc import Iterator
def parse_channels(channel_file_path: Path, mirakurun_endpoint: str) -> Iterator[str]:
yield ("#EXTM3U")
yield ("#EXTVLCOPT:network-caching=1000")
for channel in json.load(channel_file_path.open("r")):
channel_name = re.sub(r"[\u3000 \t]", "", channel["name"])
channel_type = channel["type"] # GR (known as 地上波), BS, CS
channel_id = channel["channel"]
if "services" not in channel:
yield (f"#EXTINF:-1,{channel_type} - {channel_name}")
yield (f"{mirakurun_endpoint}/api/channels/{channel_type}/{channel_id}/stream")
continue
for service in channel["services"]:
service_id = service["id"]
yield (f"#EXTINF:-1,{channel_type} - {channel_name}")
yield (f"{mirakurun_endpoint}/api/services/{service_id}/stream")
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(
description="Convert mirakurun / mirakc json file of channels into m3u8 playlist file.",
formatter_class=argparse.RawTextHelpFormatter,
epilog=dedent(
f"""
original:
https://github.com/shotantan/channels_list_conv
usage:
curl -o channels.json http://localhost:40772/api/channels
python {sys.argv[0]} channels.json > channels.m3u8
""",
),
)
parser.add_argument(
"channel_file",
help="json file of channels",
)
parser.add_argument(
"-e",
"--endpoint",
default="http://localhost:40772",
help="miraurun endpoint (default: %(default)s)",
)
return parser.parse_args()
def main() -> None:
args = parse_args()
channel_file_path = Path(args.channel_file)
mirakurun_endpoint = str(args.endpoint)
if not channel_file_path.exists():
print(f"not found: {channel_file_path}")
return
for line in parse_channels(channel_file_path, mirakurun_endpoint):
print(line)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment