diff --git a/CMakeLists.txt b/CMakeLists.txt index 026307553ab..f0195c87b43 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -171,7 +171,12 @@ if (BUILD_SOX) add_subdirectory(torchaudio/csrc/sox) endif() if (USE_FFMPEG) - add_subdirectory(third_party/ffmpeg) + if (DEFINED ENV{FFMPEG_ROOT}) + add_subdirectory(third_party/ffmpeg/single) + else() + message(STATUS "Building FFmpeg integration with multi version support") + add_subdirectory(third_party/ffmpeg/multi) + endif() add_subdirectory(torchaudio/csrc/ffmpeg) endif() if (BUILD_CUDA_CTC_DECODER) diff --git a/docs/source/build.jetson.rst b/docs/source/build.jetson.rst index 0acf194db10..b1b83d7498c 100644 --- a/docs/source/build.jetson.rst +++ b/docs/source/build.jetson.rst @@ -137,7 +137,7 @@ Verify the installation by checking the version and CUDA device accessibility. git clone https://github.com/pytorch/audio cd audio - USE_CUDA=1 USE_FFMPEG=1 pip install -v -e . --no-use-pep517 + USE_CUDA=1 pip install -v -e . --no-use-pep517 4. Check the installation ~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/source/build.linux.rst b/docs/source/build.linux.rst index 50736682c37..cd9a93bab8f 100644 --- a/docs/source/build.linux.rst +++ b/docs/source/build.linux.rst @@ -24,14 +24,7 @@ Here, we install nightly build. conda install cmake ninja pkg-config -4. Install external dependencies --------------------------------- - -.. code-block:: - - conda install -c conda-forge ffmpeg - -5. Clone the torchaudio repository +4. Clone the torchaudio repository ---------------------------------- .. code-block:: @@ -39,15 +32,29 @@ Here, we install nightly build. git clone https://github.com/pytorch/audio cd audio -6. Build +5. Build -------- .. code-block:: - USE_FFMPEG=1 python setup.py develop + python setup.py develop .. note:: Due to the complexity of build process, TorchAudio only supports in-place build. To use ``pip``, please use ``--no-use-pep517`` option. - ``USE_FFMPEG=1 pip install -v -e . --no-use-pep517`` + ``pip install -v -e . --no-use-pep517`` + +[Optional] Build TorchAudio with a custom built FFmpeg +------------------------------------------------------ + +By default, torchaudio tries to build FFmpeg extension with support for multiple FFmpeg versions. This process uses pre-built FFmpeg libraries compiled for specific CPU architectures like ``x86_64`` and ``aarch64`` (``arm64``). + +If your CPU is not one of those, then the build process can fail. To workaround, one can disable FFmpeg integration (by setting the environment variable ``USE_FFMPEG=0``) or switch to the single version FFmpeg extension. + +To build single version FFmpeg extension, FFmpeg binaries must be provided by user and available in the build environment. To do so, install FFmpeg and set ``FFMPEG_ROOT`` environment variable to specify the location of FFmpeg. + +.. code-block:: + + conda install -c conda-forge ffmpeg + FFMPEG_ROOT=${CONDA_PREFIX} python setup.py develop diff --git a/docs/source/build.windows.rst b/docs/source/build.windows.rst index 994db1fd731..302ec071229 100644 --- a/docs/source/build.windows.rst +++ b/docs/source/build.windows.rst @@ -118,10 +118,6 @@ When using conda, the directories are ``${CONDA_PREFIX}/bin``, ``${CONDA_PREFIX} conda install cmake ninja -.. code-block:: - - conda install -c conda-forge ffmpeg - 6. Build TorchAudio ------------------- @@ -136,20 +132,34 @@ Now that we have everything ready, we can build TorchAudio. .. code-block:: # In Command Prompt - set USE_FFMPEG=1 python setup.py develop .. code-block:: # In Bash - USE_FFMPEG=1 python setup.py develop + python setup.py develop .. note:: Due to the complexity of build process, TorchAudio only supports in-place build. To use ``pip``, please use ``--no-use-pep517`` option. - ``USE_FFMPEG=1 pip install -v -e . --no-use-pep517`` + ``pip install -v -e . --no-use-pep517`` + +[Optional] Build TorchAudio with a custom FFmpeg +------------------------------------------------ + +By default, torchaudio tries to build FFmpeg extension with support for multiple FFmpeg versions. This process uses pre-built FFmpeg libraries compiled for specific CPU architectures like ``x86_64``. + +If your CPU is different, then the build process can fail. To workaround, one can disable FFmpeg integration (by setting the environment variable ``USE_FFMPEG=0``) or switch to the single version FFmpeg extension. + +To build single version FFmpeg extension, FFmpeg binaries must be provided by user and available in the build environment. To do so, install FFmpeg and set ``FFMPEG_ROOT`` environment variable to specify the location of FFmpeg. + +.. code-block:: + + conda install -c conda-forge ffmpeg + FFMPEG_ROOT=${CONDA_PREFIX}/Library python setup.py develop + [Optional] Building FFmpeg from source -------------------------------------- @@ -170,6 +180,10 @@ FFmpeg's official documentation touches this https://trac.ffmpeg.org/wiki/Compil Please follow the instruction at https://www.msys2.org/ to install MSYS2. +.. note:: + + In CI environment, often `Chocolatery `_ can be used to install MSYS2. + 2. Launch MSYS2 ~~~~~~~~~~~~~~~ @@ -229,22 +243,3 @@ If the build succeeds, ``ffmpeg.exe`` should be found in the same directory. Mak Check that the resulting FFmpeg binary is accessible from Conda env Now launch a new command prompt and enable the TorchAudio development environment. Make sure that you can run the ``ffmpeg.exe`` command generated in the previous step. - -6. Build TorchAudio with the custom FFmpeg -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -To use this FFmpeg libraries for building torchaudio, do the following; -1. Uninstall ``ffmpeg`` package installed by conda. ``conda uninstall ffmpeg``. -2. When building set ``FFMPEG_ROOT`` environment variable to the directory where the libraries like ``libavcodec`` are found. - -.. code-block:: - - # In Command Prompt - set USE_FFMPEG=1 - set FFMPEG_ROOT= - python setup.py clean develop - -.. code-block:: - - # In Bash - USE_FFMPEG=1 FFMPEG_ROOT= python setup.py clean develop diff --git a/docs/source/installation.rst b/docs/source/installation.rst index dac1a408640..aa572fb097c 100644 --- a/docs/source/installation.rst +++ b/docs/source/installation.rst @@ -16,7 +16,7 @@ Please refer to https://pytorch.org/get-started/locally/ for the details. each of which requires a corresponding PyTorch distribution. .. note:: - This software was compiled against an unmodified copy of FFmpeg (licensed under `the LGPLv2.1 `_), with the specific rpath removed so as to enable the use of system libraries. The LGPL source can be downloaded `here `_. + This software was compiled against an unmodified copies of FFmpeg, with the specific rpath removed so as to enable the use of system libraries. The LGPL source can be downloaded from the following locations: `n4.1.8 `_ (`license `_), `n5.0.3 `_ (`license `_) and `n6.0 `_ (`license `_). Dependencies ------------ diff --git a/packaging/ffmpeg/build.bat b/packaging/ffmpeg/build.bat index ae7cbb24761..8e183e98e59 100644 --- a/packaging/ffmpeg/build.bat +++ b/packaging/ffmpeg/build.bat @@ -1,10 +1,9 @@ @echo off -if exist "third_party\ffmpeg\" goto end set PROJ_FOLDER=%cd% choco install -y --no-progress msys2 --package-parameters "/NoUpdate" C:\tools\msys64\usr\bin\env MSYSTEM=MINGW64 /bin/bash -l -c "pacman -S --noconfirm --needed base-devel mingw-w64-x86_64-toolchain diffutils" -C:\tools\msys64\usr\bin\env MSYSTEM=MINGW64 /bin/bash -l -c "cd ${PROJ_FOLDER} && export FFMPEG_ROOT=${PWD}/third_party/ffmpeg && packaging/vc_env_helper.bat bash ./packaging/ffmpeg/build.sh" +C:\tools\msys64\usr\bin\env MSYSTEM=MINGW64 /bin/bash -l -c "cd ${PROJ_FOLDER} && packaging/vc_env_helper.bat bash ./packaging/ffmpeg/build.sh" :end diff --git a/test/torchaudio_unittest/common_utils/case_utils.py b/test/torchaudio_unittest/common_utils/case_utils.py index 249ca6d98f1..a094f5d64f0 100644 --- a/test/torchaudio_unittest/common_utils/case_utils.py +++ b/test/torchaudio_unittest/common_utils/case_utils.py @@ -112,7 +112,7 @@ class TorchaudioTestCase(TestBaseMixin, PytorchTestCase): def is_ffmpeg_available(): - return torchaudio._extension._FFMPEG_INITIALIZED + return torchaudio._extension._FFMPEG_EXT is not None _IS_CTC_DECODER_AVAILABLE = None diff --git a/third_party/ffmpeg/CMakeLists.txt b/third_party/ffmpeg/CMakeLists.txt deleted file mode 100644 index f2feb09c611..00000000000 --- a/third_party/ffmpeg/CMakeLists.txt +++ /dev/null @@ -1,91 +0,0 @@ -################################################################################ -# This file defines the following FFmpeg libraries using pre-built binaries. - -add_library(ffmpeg4 INTERFACE) -add_library(ffmpeg ALIAS ffmpeg4) - -################################################################################ - -include(FetchContent) - -set(base_url https://pytorch.s3.amazonaws.com/torchaudio/ffmpeg) - -if (APPLE) - if ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "arm64") - FetchContent_Declare( - f4 - URL ${base_url}/2023-07-06/macos_arm64/4.1.8.tar.gz - URL_HASH SHA256=a44b8152b7f204ce5050fc7f6fd2bbbafe7ae4e45f03e135f3b45dd9a08f404e - ) - elseif ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64") - FetchContent_Declare( - f4 - URL ${base_url}/2023-07-06/macos_x86_64/4.1.8.tar.gz - URL_HASH SHA256=392d5af0b24535bfc69d6244e7595e5f07117b93d94505d0a4b34c82ae479f48 - ) - else () - message( - FATAL_ERROR - "CPU architecture ${CMAKE_SYSTEM_PROCESSOR} is not currently supported. If you do not need FFmpeg integration, then setting USE_FFMPEG=0 will bypass the issue.") - endif() -elseif (UNIX) - if ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "aarch64") - FetchContent_Declare( - f4 - URL ${base_url}/2023-07-06/linux_aarch64/4.1.8.tar.gz - URL_HASH SHA256=aae0b713040e30ceebe0d0bc82353d3d9054055c7af8a4f4abc1766015ab7681 - ) - elseif ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64") - FetchContent_Declare( - f4 - URL ${base_url}/2023-07-06/linux_x86_64/4.1.8.tar.gz - URL_HASH SHA256=52e53b8857739bdd54f9d8541e22569b57f6c6f16504ee83963c2ed3e7061a23 - ) - else () - # Possible case ppc64le (though it's not officially supported.) - message( - FATAL_ERROR - "CPU architecture ${CMAKE_SYSTEM_PROCESSOR} is not currently supported. If you do not need FFmpeg integration, then setting USE_FFMPEG=0 will bypass the issue.") - endif() -elseif(MSVC) - FetchContent_Declare( - f4 - URL ${base_url}/2023-07-06/windows/4.1.8.tar.gz - URL_HASH SHA256=c45cd36e0575490f97ace07365bb67c5e1cbe9f3e6a4272d035c19348df96790 - ) -endif() - -FetchContent_MakeAvailable(f4) -target_include_directories(ffmpeg4 INTERFACE ${f4_SOURCE_DIR}/include) - -if(APPLE) - target_link_libraries( - ffmpeg4 - INTERFACE - ${f4_SOURCE_DIR}/lib/libavutil.56.dylib - ${f4_SOURCE_DIR}/lib/libavcodec.58.dylib - ${f4_SOURCE_DIR}/lib/libavformat.58.dylib - ${f4_SOURCE_DIR}/lib/libavdevice.58.dylib - ${f4_SOURCE_DIR}/lib/libavfilter.7.dylib - ) -elseif (UNIX) - target_link_libraries( - ffmpeg4 - INTERFACE - ${f4_SOURCE_DIR}/lib/libavutil.so.56 - ${f4_SOURCE_DIR}/lib/libavcodec.so.58 - ${f4_SOURCE_DIR}/lib/libavformat.so.58 - ${f4_SOURCE_DIR}/lib/libavdevice.so.58 - ${f4_SOURCE_DIR}/lib/libavfilter.so.7 - ) -elseif(MSVC) - target_link_libraries( - ffmpeg4 - INTERFACE - ${f4_SOURCE_DIR}/bin/avutil.lib - ${f4_SOURCE_DIR}/bin/avcodec.lib - ${f4_SOURCE_DIR}/bin/avformat.lib - ${f4_SOURCE_DIR}/bin/avdevice.lib - ${f4_SOURCE_DIR}/bin/avfilter.lib - ) -endif() diff --git a/third_party/ffmpeg/multi/CMakeLists.txt b/third_party/ffmpeg/multi/CMakeLists.txt new file mode 100644 index 00000000000..5164fa75cd8 --- /dev/null +++ b/third_party/ffmpeg/multi/CMakeLists.txt @@ -0,0 +1,208 @@ +################################################################################ +# This file defines the following FFmpeg libraries using pre-built binaries. + +add_library(ffmpeg4 INTERFACE) +add_library(ffmpeg5 INTERFACE) +add_library(ffmpeg6 INTERFACE) + +################################################################################ + +include(FetchContent) + +set(base_url https://pytorch.s3.amazonaws.com/torchaudio/ffmpeg) + +if (APPLE) + if ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "arm64") + FetchContent_Declare( + f4 + URL ${base_url}/2023-07-06/macos_arm64/4.1.8.tar.gz + URL_HASH SHA256=a44b8152b7f204ce5050fc7f6fd2bbbafe7ae4e45f03e135f3b45dd9a08f404e + ) + FetchContent_Declare( + f5 + URL ${base_url}/2023-07-06/macos_arm64/5.0.3.tar.gz + URL_HASH SHA256=316fe8378afadcf63089acf3ad53a626fd3c26cc558b96ce1dc94d2a78f4deb4 + ) + FetchContent_Declare( + f6 + URL ${base_url}/2023-07-06/macos_arm64/6.0.tar.gz + URL_HASH SHA256=5d1da9626f8cb817d6c558a2c61085a3d39a8d9f725a6f69f4658bea8efa9389 + ) + elseif ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64") + FetchContent_Declare( + f4 + URL ${base_url}/2023-07-06/macos_x86_64/4.1.8.tar.gz + URL_HASH SHA256=392d5af0b24535bfc69d6244e7595e5f07117b93d94505d0a4b34c82ae479f48 + ) + FetchContent_Declare( + f5 + URL ${base_url}/2023-07-06/macos_x86_64/5.0.3.tar.gz + URL_HASH SHA256=d0b49575d3b174cfcca53b3049641855e48028cf22dd32f3334bbec4ca94f43e + ) + FetchContent_Declare( + f6 + URL ${base_url}/2023-07-06/macos_x86_64/6.0.tar.gz + URL_HASH SHA256=eabc01eb7d9e714e484d5e1b27bf7d921e87c1f3c00334abd1729e158d6db862 + ) + else () + message( + FATAL_ERROR + "${CMAKE_SYSTEM_PROCESSOR} is not supported for FFmpeg multi-version integration. " + "If you have FFmpeg libraries installed in the system," + " setting FFMPEG_ROOT environment variable to the root directory of FFmpeg installation" + " (the directory where `include` and `lib` sub directories with corresponding headers" + " and library files are present) will invoke the FFmpeg single-version integration. " + "If you do not need the FFmpeg integration, setting USE_FFMPEG=0 will bypass the issue.") + endif() +elseif (UNIX) + if ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "aarch64") + FetchContent_Declare( + f4 + URL ${base_url}/2023-07-06/linux_aarch64/4.1.8.tar.gz + URL_HASH SHA256=aae0b713040e30ceebe0d0bc82353d3d9054055c7af8a4f4abc1766015ab7681 + ) + FetchContent_Declare( + f5 + URL ${base_url}/2023-07-06/linux_aarch64/5.0.3.tar.gz + URL_HASH SHA256=65c663206982ee3f0ff88436d8869d191b46061e01e753518c77ecc13ea0236d + ) + FetchContent_Declare( + f6 + URL ${base_url}/2023-07-06/linux_aarch64/6.0.tar.gz + URL_HASH SHA256=ec762fd41ea7b8d9ad4f810f53fd78a565f2bc6f680afe56d555c80f3d35adef + ) + elseif ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64") + FetchContent_Declare( + f4 + URL ${base_url}/2023-07-06/linux_x86_64/4.1.8.tar.gz + URL_HASH SHA256=52e53b8857739bdd54f9d8541e22569b57f6c6f16504ee83963c2ed3e7061a23 + ) + FetchContent_Declare( + f5 + URL ${base_url}/2023-07-06/linux_x86_64/5.0.3.tar.gz + URL_HASH SHA256=de3c75c99b9ce33de7efdc144566804ae5880457ce71e185b3f592dc452edce7 + ) + FetchContent_Declare( + f6 + URL ${base_url}/2023-07-06/linux_x86_64/6.0.tar.gz + URL_HASH SHA256=04d3916404bab5efadd29f68361b7d13ea71e6242c6473edcb747a41a9fb97a6 + ) + else () + # Possible case ppc64le (though it's not officially supported.) + message( + FATAL_ERROR + "${CMAKE_SYSTEM_PROCESSOR} is not supported for FFmpeg multi-version integration. " + "If you have FFmpeg libraries installed in the system," + " setting FFMPEG_ROOT environment variable to the root directory of FFmpeg installation" + " (the directory where `include` and `lib` sub directories with corresponding headers" + " and library files are present) will invoke the FFmpeg single-version integration. " + "If you do not need the FFmpeg integration, setting USE_FFMPEG=0 will bypass the issue.") + endif() +elseif(MSVC) + FetchContent_Declare( + f4 + URL ${base_url}/2023-07-06/windows/4.1.8.tar.gz + URL_HASH SHA256=c45cd36e0575490f97ace07365bb67c5e1cbe9f3e6a4272d035c19348df96790 + ) + FetchContent_Declare( + f5 + URL ${base_url}/2023-07-06/windows/5.0.3.tar.gz + URL_HASH SHA256=e2daa10799909e366cb1b4b91a217d35f6749290dcfeea40ecae3d5b05a46cb3 + ) + FetchContent_Declare( + f6 + URL ${base_url}/2023-07-06/windows/6.0.tar.gz + URL_HASH SHA256=098347eca8cddb5aaa61e9ecc1a00548c645fc59b4f7346b3d91414aa00a9cf6 + ) +endif() + +FetchContent_MakeAvailable(f4 f5 f6) +target_include_directories(ffmpeg4 INTERFACE ${f4_SOURCE_DIR}/include) +target_include_directories(ffmpeg5 INTERFACE ${f5_SOURCE_DIR}/include) +target_include_directories(ffmpeg6 INTERFACE ${f6_SOURCE_DIR}/include) + +if(APPLE) + target_link_libraries( + ffmpeg4 + INTERFACE + ${f4_SOURCE_DIR}/lib/libavutil.56.dylib + ${f4_SOURCE_DIR}/lib/libavcodec.58.dylib + ${f4_SOURCE_DIR}/lib/libavformat.58.dylib + ${f4_SOURCE_DIR}/lib/libavdevice.58.dylib + ${f4_SOURCE_DIR}/lib/libavfilter.7.dylib + ) + target_link_libraries( + ffmpeg5 + INTERFACE + ${f5_SOURCE_DIR}/lib/libavutil.57.dylib + ${f5_SOURCE_DIR}/lib/libavcodec.59.dylib + ${f5_SOURCE_DIR}/lib/libavformat.59.dylib + ${f5_SOURCE_DIR}/lib/libavdevice.59.dylib + ${f5_SOURCE_DIR}/lib/libavfilter.8.dylib + ) + target_link_libraries( + ffmpeg6 + INTERFACE + ${f6_SOURCE_DIR}/lib/libavutil.58.dylib + ${f6_SOURCE_DIR}/lib/libavcodec.60.dylib + ${f6_SOURCE_DIR}/lib/libavformat.60.dylib + ${f6_SOURCE_DIR}/lib/libavdevice.60.dylib + ${f6_SOURCE_DIR}/lib/libavfilter.9.dylib + ) +elseif (UNIX) + target_link_libraries( + ffmpeg4 + INTERFACE + ${f4_SOURCE_DIR}/lib/libavutil.so.56 + ${f4_SOURCE_DIR}/lib/libavcodec.so.58 + ${f4_SOURCE_DIR}/lib/libavformat.so.58 + ${f4_SOURCE_DIR}/lib/libavdevice.so.58 + ${f4_SOURCE_DIR}/lib/libavfilter.so.7 + ) + target_link_libraries( + ffmpeg5 + INTERFACE + ${f5_SOURCE_DIR}/lib/libavutil.so.57 + ${f5_SOURCE_DIR}/lib/libavcodec.so.59 + ${f5_SOURCE_DIR}/lib/libavformat.so.59 + ${f5_SOURCE_DIR}/lib/libavdevice.so.59 + ${f5_SOURCE_DIR}/lib/libavfilter.so.8 + ) + target_link_libraries( + ffmpeg6 + INTERFACE + ${f6_SOURCE_DIR}/lib/libavutil.so.58 + ${f6_SOURCE_DIR}/lib/libavcodec.so.60 + ${f6_SOURCE_DIR}/lib/libavformat.so.60 + ${f6_SOURCE_DIR}/lib/libavdevice.so.60 + ${f6_SOURCE_DIR}/lib/libavfilter.so.9 + ) +elseif(MSVC) + target_link_libraries( + ffmpeg4 + INTERFACE + ${f4_SOURCE_DIR}/bin/avutil.lib + ${f4_SOURCE_DIR}/bin/avcodec.lib + ${f4_SOURCE_DIR}/bin/avformat.lib + ${f4_SOURCE_DIR}/bin/avdevice.lib + ${f4_SOURCE_DIR}/bin/avfilter.lib + ) + target_link_libraries( + ffmpeg5 + INTERFACE + ${f5_SOURCE_DIR}/bin/avutil.lib + ${f5_SOURCE_DIR}/bin/avcodec.lib + ${f5_SOURCE_DIR}/bin/avformat.lib + ${f5_SOURCE_DIR}/bin/avdevice.lib + ${f5_SOURCE_DIR}/bin/avfilter.lib + ) + target_link_libraries( + ffmpeg6 + INTERFACE + ${f6_SOURCE_DIR}/bin/avutil.lib + ${f6_SOURCE_DIR}/bin/avcodec.lib + ${f6_SOURCE_DIR}/bin/avformat.lib + ${f6_SOURCE_DIR}/bin/avdevice.lib + ${f6_SOURCE_DIR}/bin/avfilter.lib + ) +endif() diff --git a/third_party/ffmpeg/single/CMakeLists.txt b/third_party/ffmpeg/single/CMakeLists.txt new file mode 100644 index 00000000000..b3246c0828b --- /dev/null +++ b/third_party/ffmpeg/single/CMakeLists.txt @@ -0,0 +1,40 @@ +# CMake file for searching existing FFmpeg installation and defining ffmpeg TARGET + +message(STATUS "Searching existing FFmpeg installation") +message(STATUS FFMPEG_ROOT=$ENV{FFMPEG_ROOT}) +if (NOT DEFINED ENV{FFMPEG_ROOT}) + message(FATAL_ERROR "Environment variable FFMPEG_ROOT is not set.") +endif() + +set(_root $ENV{FFMPEG_ROOT}) +set(lib_dirs "${_root}/lib" "${_root}/bin") +set(include_dir "${_root}/include") + +add_library(ffmpeg INTERFACE) +target_include_directories(ffmpeg INTERFACE "${include_dir}") + +function (_find_ffmpeg_lib component) + find_path("${component}_header" + NAMES "lib${component}/${component}.h" + PATHS "${include_dir}" + DOC "The include directory for ${component}" + REQUIRED + NO_DEFAULT_PATH) + find_library("lib${component}" + NAMES "${component}" + PATHS ${lib_dirs} + DOC "${component} library" + REQUIRED + NO_DEFAULT_PATH) + message(STATUS "Found ${component}: ${lib${component}}") + target_link_libraries( + ffmpeg + INTERFACE + ${lib${component}}) +endfunction () + +_find_ffmpeg_lib(avutil) +_find_ffmpeg_lib(avcodec) +_find_ffmpeg_lib(avformat) +_find_ffmpeg_lib(avdevice) +_find_ffmpeg_lib(avfilter) diff --git a/tools/setup_helpers/extension.py b/tools/setup_helpers/extension.py index 685ccf05de1..c0768ce8c0a 100644 --- a/tools/setup_helpers/extension.py +++ b/tools/setup_helpers/extension.py @@ -65,12 +65,25 @@ def get_ext_modules(): ] ) if _USE_FFMPEG: - modules.extend( - [ - Extension(name="torchaudio.lib.libtorchaudio_ffmpeg", sources=[]), - Extension(name="torchaudio.lib._torchaudio_ffmpeg", sources=[]), - ] - ) + if "FFMPEG_ROOT" in os.environ: + # single version ffmpeg mode + modules.extend( + [ + Extension(name="torchaudio.lib.libtorchaudio_ffmpeg", sources=[]), + Extension(name="torchaudio.lib._torchaudio_ffmpeg", sources=[]), + ] + ) + else: + modules.extend( + [ + Extension(name="torchaudio.lib.libtorchaudio_ffmpeg4", sources=[]), + Extension(name="torchaudio.lib._torchaudio_ffmpeg4", sources=[]), + Extension(name="torchaudio.lib.libtorchaudio_ffmpeg5", sources=[]), + Extension(name="torchaudio.lib._torchaudio_ffmpeg5", sources=[]), + Extension(name="torchaudio.lib.libtorchaudio_ffmpeg6", sources=[]), + Extension(name="torchaudio.lib._torchaudio_ffmpeg6", sources=[]), + ] + ) return modules diff --git a/torchaudio/_backend/utils.py b/torchaudio/_backend/utils.py index 70361b8aa40..0e7356c78a0 100644 --- a/torchaudio/_backend/utils.py +++ b/torchaudio/_backend/utils.py @@ -6,10 +6,10 @@ import torch import torchaudio.backend.soundfile_backend as soundfile_backend -from torchaudio._extension import _FFMPEG_INITIALIZED, _SOX_INITIALIZED +from torchaudio._extension import _FFMPEG_EXT, _SOX_INITIALIZED from torchaudio.backend.common import AudioMetaData -if _FFMPEG_INITIALIZED: +if _FFMPEG_EXT is not None: from torchaudio.io._compat import info_audio, info_audio_fileobj, load_audio, load_audio_fileobj, save_audio @@ -262,7 +262,7 @@ def can_encode(uri, format) -> bool: @lru_cache(None) def get_available_backends() -> Dict[str, Backend]: backend_specs = {} - if _FFMPEG_INITIALIZED: + if _FFMPEG_EXT is not None: backend_specs["ffmpeg"] = FFmpegBackend if _SOX_INITIALIZED: backend_specs["sox"] = SoXBackend diff --git a/torchaudio/_extension/__init__.py b/torchaudio/_extension/__init__.py index 951e381ae2f..59b020d9737 100644 --- a/torchaudio/_extension/__init__.py +++ b/torchaudio/_extension/__init__.py @@ -20,7 +20,7 @@ "_IS_TORCHAUDIO_EXT_AVAILABLE", "_IS_RIR_AVAILABLE", "_SOX_INITIALIZED", - "_FFMPEG_INITIALIZED", + "_FFMPEG_EXT", ] @@ -59,11 +59,10 @@ # Initialize FFmpeg-related features -_FFMPEG_INITIALIZED = False -if is_module_available("torchaudio.lib._torchaudio_ffmpeg"): +_FFMPEG_EXT = None +if _IS_TORCHAUDIO_EXT_AVAILABLE: try: - _init_ffmpeg() - _FFMPEG_INITIALIZED = True + _FFMPEG_EXT = _init_ffmpeg() except Exception: # The initialization of FFmpeg extension will fail if supported FFmpeg # libraries are not found in the system. @@ -81,7 +80,7 @@ ) ) -fail_if_no_ffmpeg = no_op if _FFMPEG_INITIALIZED else _fail_since_no_ffmpeg +fail_if_no_ffmpeg = _fail_since_no_ffmpeg if _FFMPEG_EXT is None else no_op fail_if_no_rir = ( no_op diff --git a/torchaudio/_extension/utils.py b/torchaudio/_extension/utils.py index 30ef2e4a356..9a5c7084462 100644 --- a/torchaudio/_extension/utils.py +++ b/torchaudio/_extension/utils.py @@ -6,15 +6,17 @@ """ +import importlib +import logging import os +import platform from functools import wraps from pathlib import Path import torch - import torchaudio -from torchaudio._internal.module_utils import is_module_available +_LG = logging.getLogger(__name__) _LIB_DIR = Path(__file__).parent.parent / "lib" @@ -75,22 +77,79 @@ def _init_sox(): atexit.register(torch.ops.torchaudio.sox_effects_shutdown_sox_effects) -def _init_ffmpeg(): - if not is_module_available("torchaudio.lib._torchaudio_ffmpeg"): +def _find_ffmpeg_extension(): + # Library path for single-version FFmpeg integration + # custom source build + if _get_lib_path("_torchaudio_ffmpeg").exists(): + try: + _load_lib("libtorchaudio_ffmpeg") + except Exception as e: + raise RuntimeError("Failed to load libtorchaudio_ffmpeg.") from e + + from torchaudio.lib import _torchaudio_ffmpeg + + return _torchaudio_ffmpeg + + # Search for multi-version FFmpeg integration (OSS regular binary build) + ffmpeg_vers = [6, 5, 4] + avutil_vers = [58, 57, 56] + if all(not _get_lib_path(f"_torchaudio_ffmpeg{v}").exists() for v in ffmpeg_vers): raise RuntimeError( - "torchaudio is not compiled with FFmpeg integration. Please set USE_FFMPEG=1 when compiling torchaudio." + "Torchaudio is not built with FFmpeg integration. " "Please build torchaudio with USE_FFMPEG=1." ) - try: - _load_lib("libtorchaudio_ffmpeg") - except OSError as err: - raise ImportError("FFmpeg libraries are not found. Please install FFmpeg.") from err + libname_template = { + "Linux": "libavutil.so.{ver}", + "Darwin": "libavutil.{ver}.dylib", + "Windows": "avutil-{ver}.dll", + }[platform.system()] + + for ffmpeg_ver, avutil_ver in zip(ffmpeg_vers, avutil_vers): + _LG.debug("Attempting to load FFmpeg version %d.", ffmpeg_ver) + library = f"libtorchaudio_ffmpeg{ffmpeg_ver}" + extension = f"_torchaudio_ffmpeg{ffmpeg_ver}" + + libavutil = libname_template.format(ver=avutil_ver) + + # A simple check for FFmpeg availability. + # This is not technically sufficient as other libraries could be missing, + # but usually this is sufficient. + # + # Note: the reason why this check is performed is because I don't know + # if the next `_load_lib` (which calls ctypes.CDLL under the hood), + # could leak handle to shared libraries of dependencies, in case it fails. + # + # i.e. If the `ctypes.CDLL("foo")` fails because one of `foo`'s dependency + # does not exist while `foo` and some other dependencies exist, is it guaranteed + # that none-of them are kept in memory after the failure?? + try: + torchaudio.lib._torchaudio.find_avutil(libavutil) + except Exception as e: + _LG.debug("%s was not found. (%s)", libavutil, e) + continue + + # Note: See above comment + try: + _load_lib(library) + except Exception as e: + _LG.debug("Failed to load library, %s. (%s)", library, e) + continue - import torchaudio.lib._torchaudio_ffmpeg # noqa + _LG.debug("Found FFmpeg version %d.", ffmpeg_ver) + return importlib.import_module(f"torchaudio.lib.{extension}") + raise ImportError( + "Failed to initialize FFmpeg. " + "To see the detail of the initialization attempt, " + "please set the log level of torchaudio logger to DEBUG." + ) - torchaudio.lib._torchaudio_ffmpeg.init() - if torchaudio.lib._torchaudio_ffmpeg.get_log_level() > 8: - torchaudio.lib._torchaudio_ffmpeg.set_log_level(8) + +def _init_ffmpeg(): + ext = _find_ffmpeg_extension() + ext.init() + if ext.get_log_level() > 8: + ext.set_log_level(8) + return ext def _init_dll_path(): diff --git a/torchaudio/backend/sox_io_backend.py b/torchaudio/backend/sox_io_backend.py index 30b5cecfb0f..7908646438a 100644 --- a/torchaudio/backend/sox_io_backend.py +++ b/torchaudio/backend/sox_io_backend.py @@ -24,7 +24,7 @@ def _fail_load( raise RuntimeError("Failed to load audio from {}".format(filepath)) -if torchaudio._extension._FFMPEG_INITIALIZED: +if torchaudio._extension._FFMPEG_EXT is not None: import torchaudio.io._compat as _compat _fallback_info = _compat.info_audio diff --git a/torchaudio/csrc/ffmpeg/CMakeLists.txt b/torchaudio/csrc/ffmpeg/CMakeLists.txt index 8c08704bbcc..cf59956b613 100644 --- a/torchaudio/csrc/ffmpeg/CMakeLists.txt +++ b/torchaudio/csrc/ffmpeg/CMakeLists.txt @@ -18,30 +18,77 @@ set( compat.cpp ) +set( + ext_sources + pybind/pybind.cpp + ) + if (USE_CUDA) set( additional_lib cuda_deps) endif() -torchaudio_library( - libtorchaudio_ffmpeg - "${sources}" - "" - "torch;ffmpeg;${additional_lib}" - "" - ) - -if (BUILD_TORCHAUDIO_PYTHON_EXTENSION) - set( - ext_sources - pybind/pybind.cpp +if (TARGET ffmpeg) + torchaudio_library( + libtorchaudio_ffmpeg + "${sources}" + "" + "torch;ffmpeg;${additional_lib}" + "" ) - torchaudio_extension( - _torchaudio_ffmpeg - "${ext_sources}" + if (BUILD_TORCHAUDIO_PYTHON_EXTENSION) + torchaudio_extension( + _torchaudio_ffmpeg + "${ext_sources}" + "" + "libtorchaudio_ffmpeg" + "TORCHAUDIO_FFMPEG_EXT_NAME=_torchaudio_ffmpeg" + ) + endif() +else() + torchaudio_library( + libtorchaudio_ffmpeg4 + "${sources}" "" - "libtorchaudio_ffmpeg" + "torch;ffmpeg4;${additional_lib}" "" ) -endif () + torchaudio_library( + libtorchaudio_ffmpeg5 + "${sources}" + "" + "torch;ffmpeg5;${additional_lib}" + "" + ) + torchaudio_library( + libtorchaudio_ffmpeg6 + "${sources}" + "" + "torch;ffmpeg6;${additional_lib}" + "" + ) + if (BUILD_TORCHAUDIO_PYTHON_EXTENSION) + torchaudio_extension( + _torchaudio_ffmpeg4 + "${ext_sources}" + "" + "libtorchaudio_ffmpeg4" + "TORCHAUDIO_FFMPEG_EXT_NAME=_torchaudio_ffmpeg4" + ) + torchaudio_extension( + _torchaudio_ffmpeg5 + "${ext_sources}" + "" + "libtorchaudio_ffmpeg5" + "TORCHAUDIO_FFMPEG_EXT_NAME=_torchaudio_ffmpeg5" + ) + torchaudio_extension( + _torchaudio_ffmpeg6 + "${ext_sources}" + "" + "libtorchaudio_ffmpeg6" + "TORCHAUDIO_FFMPEG_EXT_NAME=_torchaudio_ffmpeg6" + ) + endif () +endif() diff --git a/torchaudio/csrc/ffmpeg/pybind/pybind.cpp b/torchaudio/csrc/ffmpeg/pybind/pybind.cpp index 95db01fcec3..45e7e756676 100644 --- a/torchaudio/csrc/ffmpeg/pybind/pybind.cpp +++ b/torchaudio/csrc/ffmpeg/pybind/pybind.cpp @@ -186,7 +186,11 @@ struct StreamWriterFileObj : private FileObj, public StreamWriterCustomIO { py::hasattr(fileobj, "seek") ? &seek_func : nullptr) {} }; -PYBIND11_MODULE(_torchaudio_ffmpeg, m) { +#ifndef TORCHAUDIO_FFMPEG_EXT_NAME +#error TORCHAUDIO_FFMPEG_EXT_NAME must be defined. +#endif + +PYBIND11_MODULE(TORCHAUDIO_FFMPEG_EXT_NAME, m) { m.def("init", []() { avdevice_register_all(); }); m.def("get_log_level", []() { return av_log_get_level(); }); m.def("set_log_level", [](int level) { av_log_set_level(level); }); diff --git a/torchaudio/csrc/pybind/pybind.cpp b/torchaudio/csrc/pybind/pybind.cpp index b956deb0e44..9b2f3343e31 100644 --- a/torchaudio/csrc/pybind/pybind.cpp +++ b/torchaudio/csrc/pybind/pybind.cpp @@ -8,6 +8,7 @@ PYBIND11_MODULE(_torchaudio, m) { m.def("is_rir_available", &is_rir_available, ""); m.def("is_align_available", &is_align_available, ""); m.def("cuda_version", &cuda_version, ""); + m.def("find_avutil", &find_avutil, ""); } } // namespace diff --git a/torchaudio/csrc/utils.cpp b/torchaudio/csrc/utils.cpp index 8c5898cb498..4a58c87002b 100644 --- a/torchaudio/csrc/utils.cpp +++ b/torchaudio/csrc/utils.cpp @@ -1,4 +1,4 @@ -#include +#include #include #ifdef USE_CUDA @@ -31,4 +31,10 @@ c10::optional cuda_version() { #endif } +int find_avutil(const char* name) { + auto lib = at::DynamicLibrary{name}; + auto avutil_version = (unsigned (*)(void))(lib.sym("avutil_version")); + return avutil_version() >> 16; +} + } // namespace torchaudio diff --git a/torchaudio/csrc/utils.h b/torchaudio/csrc/utils.h index 1b2be53ee87..acfc6098bd9 100644 --- a/torchaudio/csrc/utils.h +++ b/torchaudio/csrc/utils.h @@ -5,4 +5,5 @@ namespace torchaudio { bool is_rir_available(); bool is_align_available(); c10::optional cuda_version(); +int find_avutil(const char* name); } // namespace torchaudio diff --git a/torchaudio/io/_compat.py b/torchaudio/io/_compat.py index 723b7fcaeb4..aa0214b7b2b 100644 --- a/torchaudio/io/_compat.py +++ b/torchaudio/io/_compat.py @@ -7,6 +7,9 @@ from torchaudio.backend.common import AudioMetaData from torchaudio.io import StreamWriter +if torchaudio._extension._FFMPEG_EXT is not None: + StreamReaderFileObj = torchaudio._extension._FFMPEG_EXT.StreamReaderFileObj + # Note: need to comply TorchScript syntax -- need annotation and no f-string nor global def info_audio( @@ -22,7 +25,7 @@ def info_audio_fileobj( format: Optional[str], buffer_size: int = 4096, ) -> AudioMetaData: - s = torchaudio.lib._torchaudio_ffmpeg.StreamReaderFileObj(src, format, None, buffer_size) + s = StreamReaderFileObj(src, format, None, buffer_size) i = s.find_best_audio_stream() sinfo = s.get_src_stream_info(i) if sinfo.num_frames == 0: @@ -67,7 +70,7 @@ def _get_load_filter( def _load_audio_fileobj( - s: torchaudio.lib._torchaudio_ffmpeg.StreamReaderFileObj, + s: StreamReaderFileObj, filter: Optional[str] = None, channels_first: bool = True, ) -> torch.Tensor: @@ -103,7 +106,7 @@ def load_audio_fileobj( buffer_size: int = 4096, ) -> Tuple[torch.Tensor, int]: demuxer = "ogg" if format == "vorbis" else format - s = torchaudio.lib._torchaudio_ffmpeg.StreamReaderFileObj(src, demuxer, None, buffer_size) + s = StreamReaderFileObj(src, demuxer, None, buffer_size) sample_rate = int(s.get_src_stream_info(s.find_best_audio_stream()).sample_rate) filter = _get_load_filter(frame_offset, num_frames, convert) waveform = _load_audio_fileobj(s, filter, channels_first) diff --git a/torchaudio/io/_stream_reader.py b/torchaudio/io/_stream_reader.py index 684144d15be..332698d30e8 100644 --- a/torchaudio/io/_stream_reader.py +++ b/torchaudio/io/_stream_reader.py @@ -7,6 +7,11 @@ import torchaudio from torch.utils._pytree import tree_map +if torchaudio._extension._FFMPEG_EXT is not None: + _StreamReader = torchaudio._extension._FFMPEG_EXT.StreamReader + _StreamReaderFileObj = torchaudio._extension._FFMPEG_EXT.StreamReaderFileObj + + __all__ = [ "StreamReader", ] @@ -513,9 +518,9 @@ def __init__( buffer_size: int = 4096, ): if isinstance(src, str): - self._be = torchaudio.lib._torchaudio_ffmpeg.StreamReader(src, format, option) + self._be = _StreamReader(src, format, option) elif hasattr(src, "read"): - self._be = torchaudio.lib._torchaudio_ffmpeg.StreamReaderFileObj(src, format, option, buffer_size) + self._be = _StreamReaderFileObj(src, format, option, buffer_size) else: raise ValueError("`src` must be either a string or file-like object.") diff --git a/torchaudio/io/_stream_writer.py b/torchaudio/io/_stream_writer.py index 3ac6dd3d1bf..e4d46c678bc 100644 --- a/torchaudio/io/_stream_writer.py +++ b/torchaudio/io/_stream_writer.py @@ -5,10 +5,12 @@ import torchaudio -if torchaudio._extension._FFMPEG_INITIALIZED: - ConfigBase = torchaudio.lib._torchaudio_ffmpeg.CodecConfig -else: +if torchaudio._extension._FFMPEG_EXT is None: ConfigBase = object +else: + ConfigBase = torchaudio._extension._FFMPEG_EXT.CodecConfig + _StreamWriter = torchaudio._extension._FFMPEG_EXT.StreamWriter + _StreamWriterFileObj = torchaudio._extension._FFMPEG_EXT.StreamWriterFileObj @dataclass @@ -187,9 +189,9 @@ def __init__( buffer_size: int = 4096, ): if isinstance(dst, str): - self._s = torchaudio.lib._torchaudio_ffmpeg.StreamWriter(dst, format) + self._s = _StreamWriter(dst, format) elif hasattr(dst, "write"): - self._s = torchaudio.lib._torchaudio_ffmpeg.StreamWriterFileObj(dst, format, buffer_size) + self._s = _StreamWriterFileObj(dst, format, buffer_size) else: raise ValueError("`dst` must be either a string or a file-like object.") self._is_open = False diff --git a/torchaudio/utils/ffmpeg_utils.py b/torchaudio/utils/ffmpeg_utils.py index c43fdc6c169..2970c0300d6 100644 --- a/torchaudio/utils/ffmpeg_utils.py +++ b/torchaudio/utils/ffmpeg_utils.py @@ -15,7 +15,7 @@ def get_versions() -> Dict[str, Tuple[int]]: dict: mapping from library names to version string, i.e. `"libavutil": (56, 22, 100)`. """ - return torchaudio.lib._torchaudio_ffmpeg.get_versions() + return torchaudio._extension._FFMPEG_EXT.get_versions() @torchaudio._extension.fail_if_no_ffmpeg @@ -24,7 +24,7 @@ def get_log_level() -> int: See :py:func:`set_log_level` for the detailo. """ - return torchaudio.lib._torchaudio_ffmpeg.get_log_level() + return torchaudio._extension._FFMPEG_EXT.get_log_level() @torchaudio._extension.fail_if_no_ffmpeg @@ -61,7 +61,7 @@ def set_log_level(level: int): Extremely verbose debugging, useful for libav* development. """ - torchaudio.lib._torchaudio_ffmpeg.set_log_level(level) + torchaudio._extension._FFMPEG_EXT.set_log_level(level) @torchaudio._extension.fail_if_no_ffmpeg @@ -79,7 +79,7 @@ def get_demuxers() -> Dict[str, str]: ... aax: CRI AAX ... ac3: raw AC-3 """ - return torchaudio.lib._torchaudio_ffmpeg.get_demuxers() + return torchaudio._extension._FFMPEG_EXT.get_demuxers() @torchaudio._extension.fail_if_no_ffmpeg @@ -98,7 +98,7 @@ def get_muxers() -> Dict[str, str]: ... adx: CRI ADX ... aiff: Audio IFF """ - return torchaudio.lib._torchaudio_ffmpeg.get_muxers() + return torchaudio._extension._FFMPEG_EXT.get_muxers() @torchaudio._extension.fail_if_no_ffmpeg @@ -117,7 +117,7 @@ def get_audio_decoders() -> Dict[str, str]: ... adx: CRI ADX ... aiff: Audio IFF """ - return torchaudio.lib._torchaudio_ffmpeg.get_audio_decoders() + return torchaudio._extension._FFMPEG_EXT.get_audio_decoders() @torchaudio._extension.fail_if_no_ffmpeg @@ -137,7 +137,7 @@ def get_audio_encoders() -> Dict[str, str]: ... ac3_fixed: ATSC A/52A (AC-3) ... alac: ALAC (Apple Lossless Audio Codec) """ - return torchaudio.lib._torchaudio_ffmpeg.get_audio_encoders() + return torchaudio._extension._FFMPEG_EXT.get_audio_encoders() @torchaudio._extension.fail_if_no_ffmpeg @@ -157,7 +157,7 @@ def get_video_decoders() -> Dict[str, str]: ... amv: AMV Video ... anm: Deluxe Paint Animation """ - return torchaudio.lib._torchaudio_ffmpeg.get_video_decoders() + return torchaudio._extension._FFMPEG_EXT.get_video_decoders() @torchaudio._extension.fail_if_no_ffmpeg @@ -178,7 +178,7 @@ def get_video_encoders() -> Dict[str, str]: ... asv1: ASUS V1 ... asv2: ASUS V2 """ - return torchaudio.lib._torchaudio_ffmpeg.get_video_encoders() + return torchaudio._extension._FFMPEG_EXT.get_video_encoders() @torchaudio._extension.fail_if_no_ffmpeg @@ -194,7 +194,7 @@ def get_input_devices() -> Dict[str, str]: ... avfoundation: AVFoundation input device ... lavfi: Libavfilter virtual input device """ - return torchaudio.lib._torchaudio_ffmpeg.get_input_devices() + return torchaudio._extension._FFMPEG_EXT.get_input_devices() @torchaudio._extension.fail_if_no_ffmpeg @@ -209,7 +209,7 @@ def get_output_devices() -> Dict[str, str]: >>> print(f"{k}: {v}") ... audiotoolbox: AudioToolbox output device """ - return torchaudio.lib._torchaudio_ffmpeg.get_output_devices() + return torchaudio._extension._FFMPEG_EXT.get_output_devices() @torchaudio._extension.fail_if_no_ffmpeg @@ -223,7 +223,7 @@ def get_input_protocols() -> List[str]: >>> print(get_input_protocols()) ... ['file', 'ftp', 'hls', 'http','https', 'pipe', 'rtmp', 'tcp', 'tls', 'udp', 'unix'] """ - return torchaudio.lib._torchaudio_ffmpeg.get_input_protocols() + return torchaudio._extension._FFMPEG_EXT.get_input_protocols() @torchaudio._extension.fail_if_no_ffmpeg @@ -237,7 +237,7 @@ def get_output_protocols() -> List[str]: >>> print(get_output_protocols()) ... ['file', 'ftp', 'http', 'https', 'md5', 'pipe', 'prompeg', 'rtmp', 'tee', 'tcp', 'tls', 'udp', 'unix'] """ - return torchaudio.lib._torchaudio_ffmpeg.get_output_protocols() + return torchaudio._extension._FFMPEG_EXT.get_output_protocols() @torchaudio._extension.fail_if_no_ffmpeg @@ -251,10 +251,10 @@ def get_build_config() -> str: >>> print(get_build_config()) --prefix=/Users/runner/miniforge3 --cc=arm64-apple-darwin20.0.0-clang --enable-gpl --enable-hardcoded-tables --enable-libfreetype --enable-libopenh264 --enable-neon --enable-libx264 --enable-libx265 --enable-libaom --enable-libsvtav1 --enable-libxml2 --enable-libvpx --enable-pic --enable-pthreads --enable-shared --disable-static --enable-version3 --enable-zlib --enable-libmp3lame --pkg-config=/Users/runner/miniforge3/conda-bld/ffmpeg_1646229390493/_build_env/bin/pkg-config --enable-cross-compile --arch=arm64 --target-os=darwin --cross-prefix=arm64-apple-darwin20.0.0- --host-cc=/Users/runner/miniforge3/conda-bld/ffmpeg_1646229390493/_build_env/bin/x86_64-apple-darwin13.4.0-clang # noqa """ - return torchaudio.lib._torchaudio_ffmpeg.get_build_config() + return torchaudio._extension._FFMPEG_EXT.get_build_config() @torchaudio._extension.fail_if_no_ffmpeg def clear_cuda_context_cache(): """Clear the CUDA context used by CUDA Hardware accelerated video decoding""" - torchaudio.lib._torchaudio_ffmpeg.clear_cuda_context_cache() + torchaudio._extension._FFMPEG_EXT.clear_cuda_context_cache()