Mercurial > hg > config
annotate python/example/m3u.py @ 928:84543f2cda0d
restore my real email that companies keep making me change
| author | Jeff Hammel <k0scist@gmail.com> | 
|---|---|
| date | Tue, 14 Oct 2025 14:20:55 -0700 | 
| parents | e6fb1a8fe66b | 
| children | 
| rev | line source | 
|---|---|
| 
752
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
1 #!/usr/bin/env python | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
2 # -*- coding: utf-8 -*- | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
3 | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
4 """ | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
5 m3u playlist manipulator | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
6 | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
7 See: | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
8 - https://pypi.python.org/pypi/m3u8 | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
9 - http://gonze.com/playlists/playlist-format-survey.html#M3U | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
10 - http://www.assistanttools.com/articles/m3u_playlist_format.shtml | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
11 - http://en.wikipedia.org/wiki/M3U | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
12 - http://tools.ietf.org/html/draft-pantos-http-live-streaming-08#section-3.3.1 | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
13 """ | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
14 | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
15 # imports | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
16 import argparse | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
17 import m3u8 | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
18 import os | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
19 import subprocess | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
20 import sys | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
21 | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
22 # module globals | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
23 __all__ = ['main', 'M3UParser'] | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
24 here = os.path.dirname(os.path.realpath(__file__)) | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
25 string = (str, unicode) | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
26 | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
27 class Playlist(object): | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
28 def __init__(self, playlists=(), base_path=None): | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
29 self.clips = [] | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
30 for playlist in playlists: | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
31 assert os.path.isfile(playlist) | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
32 _base_path = os.path.abspath(base_path or os.path.dirname(os.path.abspath(playlist))) # TODO: this doesn't fix URLs | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
33 content = open(playlist).read() | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
34 m3u = m3u8.M3U8(content, base_path=_base_path) | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
35 for segment in m3u.segments: | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
36 path = segment.uri | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
37 title = segment.title | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
38 self.clips.append((title, path)) | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
39 | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
40 def __str__(self): | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
41 retval = [] | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
42 for title, path in self.clips: | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
43 if title: | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
44 line = '{} # {}'.format(os.path.abspath(path), title) | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
45 else: | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
46 line = os.path.abspath(path) | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
47 retval.append(line) | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
48 return '\n'.join(retval) | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
49 | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
50 class M3UParser(argparse.ArgumentParser): | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
51 """CLI option parser""" | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
52 def __init__(self, **kwargs): | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
53 kwargs.setdefault('description', __doc__) | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
54 argparse.ArgumentParser.__init__(self, **kwargs) | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
55 self.add_argument('playlists', metavar='playlist', nargs='+', | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
56 help="playlist to parse") | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
57 self.add_argument('-b', '--base', dest='base_path', default=os.getcwd(), | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
58 help="base path [DEFAULT: %(default)s]") | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
59 self.options = None | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
60 | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
61 def parse_args(self, *args, **kw): | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
62 options = argparse.ArgumentParser.parse_args(self, *args, **kw) | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
63 self.validate(options) | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
64 self.options = options | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
65 return options | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
66 | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
67 def validate(self, options): | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
68 """validate options""" | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
69 if not os.path.exists(options.base_path): | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
70 self.error("Base path '{}' does not exist".format(options.base_path)) | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
71 missing = [i for i in options.playlists | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
72 if not os.path.exists(i)] | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
73 if missing: | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
74 self.error("Playlist not found: {}".format(', '.join(missing))) | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
75 | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
76 def main(args=sys.argv[1:]): | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
77 """CLI""" | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
78 | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
79 # parse command line options | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
80 parser = M3UParser() | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
81 options = parser.parse_args(args) | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
82 | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
83 # create playlist | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
84 playlist = Playlist(options.playlists, options.base_path) | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
85 | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
86 # print out some things | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
87 print ('{}'.format(playlist)) | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
88 | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
89 if __name__ == '__main__': | 
| 
 
e6fb1a8fe66b
add example for m3u playlists [status: unknown]
 
Jeff Hammel <k0scist@gmail.com> 
parents:  
diff
changeset
 | 
90 main() | 
