Skip to content

Commit

Permalink
Add support for new argument ch_layout on ffmpeg >= 7
Browse files Browse the repository at this point in the history
  • Loading branch information
osaajani committed Jan 17, 2025
1 parent bbe4d4a commit da7d9f7
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 12 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Improve perfs of decorator by pre-computing arguments
- Fix textclip being cut or of impredictable height (see issues #2325, #2260 and #2268)
- Fix TimeMirror and TimeSymmetrize cutting last second of clip
- Fix audiopreview not working with ffplay >= 7.0.0

## [v2.1.2](https://github.com/zulko/moviepy/tree/master)

Expand Down
28 changes: 18 additions & 10 deletions moviepy/audio/io/ffplay_audiopreviewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from moviepy.config import FFPLAY_BINARY
from moviepy.decorators import requires_duration
from moviepy.tools import cross_platform_popen_params

from moviepy.video.io import ffmpeg_tools

class FFPLAY_AudioPreviewer:
"""
Expand All @@ -24,7 +24,6 @@ class FFPLAY_AudioPreviewer:
nchannels:
Number of audio channels in the clip. Default to 2 channels.
"""

def __init__(
Expand All @@ -42,8 +41,22 @@ def __init__(
"s%dle" % (8 * nbytes),
"-ar",
"%d" % fps_input,
"-ac",
"%d" % nchannels,
]

# Adapt number of channels argument to ffplay version
ffplay_version = ffmpeg_tools.ffplay_version()[1]
if int(ffplay_version.split('.')[0]) >= 7:
cmd += [
"-ch_layout",
"stereo" if nchannels == 2 else "mono",
]
else :
cmd += [
"-ac",
"%d" % nchannels,
]

cmd += [
"-i",
"-",
]
Expand All @@ -62,12 +75,7 @@ def write_frames(self, frames_array):
_, ffplay_error = self.proc.communicate()
if ffplay_error is not None:
ffplay_error = ffplay_error.decode()
else:
# The error was redirected to a logfile with `write_logfile=True`,
# so read the error from that file instead
self.logfile.seek(0)
ffplay_error = self.logfile.read()


error = (
f"{err}\n\nMoviePy error: FFPLAY encountered the following error while "
f":\n\n {ffplay_error}"
Expand Down
2 changes: 1 addition & 1 deletion moviepy/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "2.1.1"
__version__ = "2.1.2"
87 changes: 86 additions & 1 deletion moviepy/video/io/ffmpeg_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

import os

from moviepy.config import FFMPEG_BINARY
import subprocess

import re

from moviepy.config import FFMPEG_BINARY, FFPLAY_BINARY
from moviepy.decorators import convert_parameter_to_seconds, convert_path_to_string
from moviepy.tools import ffmpeg_escape_filename, subprocess_call

Expand Down Expand Up @@ -207,3 +211,84 @@ def ffmpeg_stabilize_video(
cmd.append("-y")

subprocess_call(cmd, logger=logger)


def ffmpeg_version():
"""
Retrieve the FFmpeg version.
This function retrieves both the full and numeric version of FFmpeg
by executing the `ffmpeg -version` command. The full version includes
additional details like build information, while the numeric version
contains only the version numbers (e.g., '7.0.2').
Return
------
tuple
A tuple containing:
- `full_version` (str): The complete version string (e.g., '7.0.2-static').
- `numeric_version` (str): The numeric version string (e.g., '7.0.2').
Example
-------
>>> ffmpeg_version()
('7.0.2-static', '7.0.2')
Raises
------
subprocess.CalledProcessError
If the FFmpeg command fails to execute properly.
"""
cmd = [
FFMPEG_BINARY,
"-version",
"-v"
"quiet",
]

result = subprocess.run(cmd, capture_output=True, text=True, check=True)

# Extract the version number from the first line of output
full_version = result.stdout.splitlines()[0].split()[2]
numeric_version = re.match(r'^[0-9.]+', full_version).group(0)
return (full_version, numeric_version)


def ffplay_version():
"""
Retrieve the FFplay version.
This function retrieves both the full and numeric version of FFplay
by executing the `ffplay -version` command. The full version includes
additional details like build information, while the numeric version
contains only the version numbers (e.g., '6.0.1').
Return
------
tuple
A tuple containing:
- `full_version` (str): The complete version string (e.g., '6.0.1-static').
- `numeric_version` (str): The numeric version string (e.g., '6.0.1').
Example
-------
>>> ffplay_version()
('6.0.1-static', '6.0.1')
Raises
------
subprocess.CalledProcessError
If the FFplay command fails to execute properly.
"""
cmd = [
FFPLAY_BINARY,
"-version",
]

result = subprocess.run(cmd, capture_output=True, text=True, check=True)
# Extract the version number from the first line of output
full_version = result.stdout.splitlines()[0].split()[2]
numeric_version = re.match(r'^[0-9.]+', full_version).group(0)
return (full_version, numeric_version)


0 comments on commit da7d9f7

Please sign in to comment.