Cancel a media-processing job and clean up partial output

Cancelling a media export should stop its child process and prevent a partial file from looking complete. Give each job a private temporary destination, wait for the process to finish stopping, and promote an output only after successful completion and validation.
Exercise cancellation without an encoder
This disposable Python fixture starts a sleeping child that creates a known partial file. The ready message avoids guessing whether the child has reached the write before cancellation. All files belong to a temporary directory.
import subprocess
import sys
from pathlib import Path
from tempfile import TemporaryDirectory
with TemporaryDirectory() as folder:
partial = Path(folder) / "export.part"
child = "from pathlib import Path; import sys,time; Path(sys.argv[1]).write_text('partial'); print('ready',flush=True); time.sleep(30)"
process = subprocess.Popen([sys.executable, "-c", child, str(partial)], stdout=subprocess.PIPE, text=True)
assert process.stdout.readline().strip() == "ready"
process.terminate()
try:
process.communicate(timeout=2)
except subprocess.TimeoutExpired:
process.kill()
process.communicate()
partial.unlink(missing_ok=True)
assert process.poll() is not None and not partial.exists()
The fixture tests one direct child. It is not a complete process-tree cancellation implementation and does not run FFmpeg. A wrapper that launches descendants may require a process group or an operating-system-specific job mechanism.
Cleanup follows confirmed child exit and removes only the cancelled job's partial output.
Keep cleanup scoped
Delete only paths assigned to the cancelled job. Do not scan an entire export directory for filenames that look temporary. A second job may be using a similar filename, and a user may have placed unrelated work nearby. Keep the final destination separate so that cancellation cannot remove an earlier successful export.
Python documents that a timeout in communicate does not kill the child automatically. After termination or a forced kill, finish communication and collect the return state. Bound captured output for a real encoder because a long diagnostic stream can consume substantial memory.
Distinguish stop from success
Record cancellation as its own outcome. A nonzero process result caused by a user cancellation should not silently trigger an encoder fallback. Check the cancellation state before starting another attempt or moving a file into its final location. Test cancellation just before completion too, when success and stop events can race.
Reference: Python subprocess management. ShortForge provides related export-workflow context; this fixture is independent of its current process manager.