Coverage for pyguymer3/media/optimise_MP4.py: 4%
26 statements
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-08 18:47 +0000
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-08 18:47 +0000
1#!/usr/bin/env python3
3# Define function ...
4def optimise_MP4(
5 fname1,
6 /,
7 *,
8 chunksize = 1048576,
9 debug = __debug__,
10 mp4filePath = None,
11 timeout = 60.0,
12):
13 """
14 "mp4file" does modify, and it does touch, the MP4 even if it cannot optimise
15 it, therefore it is NOT safe to keep on running "mp4file" on the same MP4
16 over and over again.
17 """
19 # Import standard modules ...
20 import os
21 import shutil
22 import subprocess
23 import tempfile
25 # Import sub-functions ...
26 from .does_MP4_have_free import does_MP4_have_free
27 from .is_moov_at_beginning_of_MP4 import is_moov_at_beginning_of_MP4
28 from ..sha512_of_MP4 import sha512_of_MP4
30 # **************************************************************************
32 # Try to find the paths if the user did not provide them ...
33 if mp4filePath is None:
34 mp4filePath = shutil.which("mp4file")
35 assert mp4filePath is not None, "\"mp4file\" is not installed"
37 # Check that the MP4 exists ...
38 if not os.path.exists(fname1):
39 raise Exception(f"\"{fname1}\" does not exist") from None
41 # Skip this MP4 if it does not have any "free" atoms and if the "moov" atom
42 # is before the "mdat" atom ...
43 if not does_MP4_have_free(fname1) and is_moov_at_beginning_of_MP4(fname1):
44 if debug:
45 print(f"INFO: Skipping because \"{fname1}\" does not have any \"free\" atoms and the \"moov\" atom is before the \"mdat\" atom")
46 return
48 # Create temporary directory ...
49 with tempfile.TemporaryDirectory(prefix = "optimise_MP4.") as tname:
50 # Copy the MP4 into the temporary directory ...
51 shutil.copy(fname1, tname)
53 # Deduce the MP4 name in the temporary directory ...
54 fname2 = f"{tname}/{os.path.basename(fname1)}"
56 # Optimise MP4 ...
57 subprocess.run(
58 [
59 mp4filePath,
60 "--optimize",
61 fname2,
62 ],
63 check = True,
64 encoding = "utf-8",
65 stderr = subprocess.DEVNULL,
66 stdout = subprocess.DEVNULL,
67 timeout = timeout,
68 )
70 # Find the two hashes and don't replace the original if the new one is
71 # the same ...
72 if sha512_of_MP4(
73 fname1,
74 chunksize = chunksize,
75 ignoreModificationTime = True,
76 ) == sha512_of_MP4(
77 fname2,
78 chunksize = chunksize,
79 ignoreModificationTime = True,
80 ):
81 if debug:
82 print(f"INFO: Skipping because \"{fname2}\" is the same as \"{fname1}\"")
83 return
85 # Replace the original ...
86 shutil.move(fname2, fname1)