Skip to content

Commit 94665fc

Browse files
committed
simplify play threads examples
1 parent 5c1ba3d commit 94665fc

File tree

6 files changed

+51
-72
lines changed

6 files changed

+51
-72
lines changed

README.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,16 @@ If the FFprobe task was in an asyncio.gather() algorithm, resource utilization c
3131
Thus we have a "win-win" by using asyncio generator for FFprobe--the throttling comes implicitly from other parts of the pipeline.
3232

3333

34-
### play_threadpool.py
34+
### Threading
3535

36-
Even though coroutines are more efficient in many applications, the syntax of `concurrent.futures.ThreadPoolExecutor` is perhaps the simplest possible way to spawn independent processes in a controlled fashion
36+
Even though coroutines are more efficient in many applications, the syntax of `concurrent.futures.ThreadPoolExecutor` is perhaps the simplest possible way to spawn independent processes in a controlled fashion.
3737

38-
### play_coroutine.py
38+
* play_thread.py: use ThreadPoolExecutor without queue
39+
* play_thread_queue.py: use ThreadPoolExecutor with queue
3940

40-
Use Python `asyncio` coroutine event loop to spawn processes.
41+
### Coroutine
42+
43+
* play_coroutine.py: `asyncio` coroutine event loop to spawn processes.
4144

4245
### Fortran
4346

play_coroutine.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
"-suffix",
1414
help="file suffixes of desired media file types",
1515
nargs="+",
16-
default=[".mp4", ".avi", ".ogv", ".wmv", ".flv", ".mov", ".ogg"],
1716
)
1817
P = p.parse_args()
1918

play_queue.py

Lines changed: 0 additions & 40 deletions
This file was deleted.

play_threadpool.py renamed to play_thread.py

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,7 @@
1313

1414

1515
def ffplay(filein: Path):
16-
17-
if not filein.is_file():
18-
raise FileNotFoundError(filein)
19-
20-
cmd = [EXE, "-v", "warning", "-autoexit", str(filein)]
21-
22-
subprocess.check_call(cmd)
16+
subprocess.check_call([EXE, "-v", "warning", "-autoexit", str(filein)])
2317

2418

2519
if __name__ == "__main__":

play_thread_queue.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#!/usr/bin/env python3
2+
from argparse import ArgumentParser
3+
import concurrent.futures
4+
import queue
5+
from pathlib import Path
6+
import shutil
7+
import subprocess
8+
9+
from asyncioffmpeg import get_videos
10+
11+
EXE = shutil.which("ffplay")
12+
if not EXE:
13+
raise FileNotFoundError("ffplay")
14+
15+
16+
def ffplay(filein: Path):
17+
subprocess.check_call([EXE, "-v", "warning", "-autoexit", str(filein)])
18+
19+
20+
def main(qin: queue.Queue):
21+
with concurrent.futures.ThreadPoolExecutor(max_workers=2, thread_name_prefix="ffplay") as pool:
22+
while not qin.empty():
23+
pool.submit(ffplay, qin.get(timeout=1.0))
24+
qin.task_done()
25+
26+
27+
if __name__ == "__main__":
28+
p = ArgumentParser(description="Asynchronous playback with ThreadPool and FFplay")
29+
p.add_argument("path", help="directory where media files are kept")
30+
p.add_argument(
31+
"-suffix", help="file suffixes of desired media file types", nargs="+",
32+
)
33+
P = p.parse_args()
34+
35+
flist = get_videos(P.path, P.suffix)
36+
print("found", len(flist), "files in", P.path)
37+
38+
qin = queue.Queue() # type: ignore
39+
for fn in flist:
40+
qin.put(fn)
41+
42+
main(qin)
43+
qin.join()

src/asyncioffmpeg/ffplay.py

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
This is more effective than endless context switching for an overloaded CPU.
44
"""
55

6-
import queue
7-
import subprocess
86
import asyncio
97
from pathlib import Path
108
import shutil
@@ -62,21 +60,3 @@ async def main(flist: Iterable[Path]):
6260
task.cancel()
6361

6462
await asyncio.gather(*tasks, return_exceptions=True)
65-
66-
67-
def ffplay_sync(qin: queue.Queue):
68-
"""
69-
Play media synchronously
70-
"""
71-
72-
while not qin.empty():
73-
filein = qin.get(timeout=1.0)
74-
75-
cmd = [FFPLAY, "-v", "warning", "-autoexit", str(filein)]
76-
77-
ret = subprocess.run(cmd)
78-
79-
if ret.returncode != 0:
80-
print(filein, "playback failure", cmd, file=sys.stderr)
81-
82-
qin.task_done()

0 commit comments

Comments
 (0)