Commit 877a88c5 authored by moto's avatar moto Committed by Facebook GitHub Bot
Browse files

Make FFmpeg log level configurable (#2439)

Summary:
Undesired logs are one of the loudest UX complains we get.
Yet, loading media files involves uncertainty which is
difficult to debug without debug log.

This commit introduces utility functions to configure logging level
so that we can ask users to enable it when they encounter an issue,
while defaulting to non-verbose option.

Pull Request resolved: https://github.com/pytorch/audio/pull/2439

Reviewed By: hwangjeff, xiaohui-zhang

Differential Revision: D36903763

Pulled By: mthrok

fbshipit-source-id: f4ddd9915b13197c2a2eb97e965005b8b5b8d987
parent 3229fc55
...@@ -11,3 +11,11 @@ This affects functionalities in :ref:`Sox IO backend<sox_io_backend>` and :ref:` ...@@ -11,3 +11,11 @@ This affects functionalities in :ref:`Sox IO backend<sox_io_backend>` and :ref:`
.. automodule:: torchaudio.utils.sox_utils .. automodule:: torchaudio.utils.sox_utils
:members: :members:
torchaudio.utils.ffmpeg_utils
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Utility module to configure FFmpeg libraries.
.. automodule:: torchaudio.utils.ffmpeg_utils
:members:
...@@ -8,6 +8,7 @@ import time ...@@ -8,6 +8,7 @@ import time
import unittest import unittest
import torch import torch
import torchaudio
from torch.testing._internal.common_utils import TestCase as PytorchTestCase from torch.testing._internal.common_utils import TestCase as PytorchTestCase
from torchaudio._internal.module_utils import ( from torchaudio._internal.module_utils import (
is_kaldi_available, is_kaldi_available,
...@@ -112,22 +113,8 @@ class TorchaudioTestCase(TestBaseMixin, PytorchTestCase): ...@@ -112,22 +113,8 @@ class TorchaudioTestCase(TestBaseMixin, PytorchTestCase):
pass pass
_IS_FFMPEG_AVAILABLE = None
def is_ffmpeg_available(): def is_ffmpeg_available():
if _eval_env("TORCHAUDIO_TEST_IN_FBCODE", default=False): return torchaudio._extension._FFMPEG_INITIALIZED
return True
global _IS_FFMPEG_AVAILABLE
if _IS_FFMPEG_AVAILABLE is None:
try:
from torchaudio.io import StreamReader # noqa: F401
_IS_FFMPEG_AVAILABLE = True
except Exception:
_IS_FFMPEG_AVAILABLE = False
return _IS_FFMPEG_AVAILABLE
_IS_CTC_DECODER_AVAILABLE = None _IS_CTC_DECODER_AVAILABLE = None
......
from torchaudio.utils import ffmpeg_utils
from torchaudio_unittest.common_utils import PytorchTestCase, skipIfNoFFmpeg
@skipIfNoFFmpeg
class TestFFmpegUtils(PytorchTestCase):
"""Smoke test for ffmpeg_utils module"""
def tearDown(self):
ffmpeg_utils.set_log_level(8)
super().tearDown()
def test_get_log_level(self):
"""`get_log_level` does not exhibit abnormal behavior"""
for _ in range(10):
ffmpeg_utils.get_log_level()
def test_set_log_level(self):
"""`set_log_level` persists log level"""
for i in range(-100, 100):
ffmpeg_utils.set_log_level(i)
assert ffmpeg_utils.get_log_level() == i
...@@ -29,11 +29,12 @@ c10::intrusive_ptr<StreamReaderBinding> init( ...@@ -29,11 +29,12 @@ c10::intrusive_ptr<StreamReaderBinding> init(
using S = const c10::intrusive_ptr<StreamReaderBinding>&; using S = const c10::intrusive_ptr<StreamReaderBinding>&;
TORCH_LIBRARY_FRAGMENT(torchaudio, m) { TORCH_LIBRARY_FRAGMENT(torchaudio, m) {
m.def("torchaudio::ffmpeg_init", []() { m.def("torchaudio::ffmpeg_init", []() { avdevice_register_all(); });
avdevice_register_all(); m.def("torchaudio::ffmpeg_get_log_level", []() -> int64_t {
if (av_log_get_level() == AV_LOG_INFO) { return static_cast<int64_t>(av_log_get_level());
av_log_set_level(AV_LOG_ERROR); });
} m.def("torchaudio::ffmpeg_set_log_level", [](int64_t level) {
av_log_set_level(static_cast<int>(level));
}); });
m.class_<StreamReaderBinding>("ffmpeg_StreamReader") m.class_<StreamReaderBinding>("ffmpeg_StreamReader")
.def(torch::init<>(init)) .def(torch::init<>(init))
......
from torchaudio._internal import module_utils as _mod_utils from torchaudio._internal import module_utils as _mod_utils
from . import sox_utils from . import ffmpeg_utils, sox_utils
from .download import download_asset from .download import download_asset
if _mod_utils.is_sox_available(): if _mod_utils.is_sox_available():
sox_utils.set_verbosity(0) sox_utils.set_verbosity(0)
__all__ = [ __all__ = [
"download_asset", "download_asset",
"sox_utils", "sox_utils",
"ffmpeg_utils",
] ]
import torch
def get_log_level() -> int:
"""Get the log level of FFmpeg.
See :py:func:`set_log_level` for the detailo.
"""
return torch.ops.torchaudio.ffmpeg_get_log_level()
def set_log_level(level: int):
"""Set the log level of FFmpeg (libavformat etc)
Arguments:
level (int): Log level. The larger, the more verbose.
The following values are common values, the corresponding ``ffmpeg``'s
``-loglevel`` option value and desription.
* ``-8`` (``quiet``):
Print no output.
* ``0`` (``panic``):
Something went really wrong and we will crash now.
* ``8`` (``fatal``):
Something went wrong and recovery is not possible.
For example, no header was found for a format which depends
on headers or an illegal combination of parameters is used.
* ``16`` (``error``):
Something went wrong and cannot losslessly be recovered.
However, not all future data is affected.
* ``24`` (``warning``):
Something somehow does not look correct.
This may or may not lead to problems.
* ``32`` (``info``):
Standard information.
* ``40`` (``verbose``):
Detailed information.
* ``48`` (``debug``):
Stuff which is only useful for libav* developers.
* ``56`` (``trace``):
Extremely verbose debugging, useful for libav* development.
"""
torch.ops.torchaudio.ffmpeg_set_log_level(level)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment