├── .all-contributorsrc ├── .gitchangelog.rc ├── .gitchangelog.tpl ├── .github ├── CONTRIBUTING.md ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── feature_request.md │ └── question.md └── workflows │ └── python-package.yml ├── .gitignore ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── docs ├── ffmpeg_bitrate_stats.html ├── index.html └── search.js ├── ffmpeg_bitrate_stats ├── __init__.py ├── __main__.py ├── bitrate_stats.py ├── log.py └── py.typed ├── requirements.dev.txt ├── requirements.txt ├── setup.cfg ├── setup.py └── test ├── test.mp4 ├── test.py ├── test_keyframes.mp4 └── without_timestamps.mp4 /.all-contributorsrc: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "README.md" 4 | ], 5 | "imageSize": 100, 6 | "commit": false, 7 | "commitType": "docs", 8 | "commitConvention": "angular", 9 | "contributors": [ 10 | { 11 | "login": "GabrielChanzy", 12 | "name": "GabrielChanzy", 13 | "avatar_url": "https://avatars.githubusercontent.com/u/43713708?v=4", 14 | "profile": "https://github.com/GabrielChanzy", 15 | "contributions": [ 16 | "code" 17 | ] 18 | } 19 | ], 20 | "contributorsPerLine": 7, 21 | "skipCi": true, 22 | "repoType": "github", 23 | "repoHost": "https://github.com", 24 | "projectName": "ffmpeg-bitrate-stats", 25 | "projectOwner": "slhck" 26 | } 27 | -------------------------------------------------------------------------------- /.gitchangelog.rc: -------------------------------------------------------------------------------- 1 | output_engine = mustache(".gitchangelog.tpl") 2 | 3 | section_regexps = [ 4 | ('', None) 5 | ] 6 | 7 | subject_process = (strip | ucfirst | final_dot) 8 | 9 | tag_filter_regexp = r'^v[0-9]+\.[0-9]+(\.[0-9]+)?$' 10 | 11 | ignore_regexps = [ 12 | r'^Bump version to' 13 | ] 14 | -------------------------------------------------------------------------------- /.gitchangelog.tpl: -------------------------------------------------------------------------------- 1 | {{#general_title}} 2 | # {{{title}}} 3 | 4 | {{/general_title}} 5 | 6 | {{#versions}} 7 | ## {{{label}}} 8 | 9 | {{#sections}} 10 | {{#commits}} 11 | * {{{subject}}} 12 | {{#body}} 13 | 14 | {{{body_indented}}} 15 | {{/body}} 16 | 17 | {{/commits}} 18 | {{/sections}} 19 | 20 | {{/versions}} -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Features and Bugfixes 2 | 3 | If you want to contribute a new feature or fix, please: 4 | 5 | - Check if there isn't any open issue for the same problem 6 | - Fork the project 7 | - Implement your feature or fix 8 | - Bonus points if you provide a test case in `test/test.py` 9 | - Provide a commit for the change you want to make (one feature per commit, please) 10 | - Create a pull request 11 | 12 | ## Issues and Questions 13 | 14 | If you simply have a question or want to raise an issue, head to the issue tracker. There's a template there that you're kindly asked to fill out. It helps me understand what the problem might be. -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: slhck # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: I ran across an error or bug in the program 4 | 5 | --- 6 | 7 | **:warning: Please read this carefully and edit the example responses! If you do not fill out this information, your bug report may be closed without comment.** 8 | 9 | **Checklist** (please tick all boxes) 10 | - [ ] I am using the latest version of `ffmpeg-bitrate-stats` (run `pip3 install --upgrade ffmpeg-bitrate-stats`) 11 | - [ ] I am using the latest stable version of `ffmpeg` or a recent build from Git master 12 | 13 | **Expected behavior** 14 | A clear and concise description of what you expected to happen. 15 | 16 | **Actual behavior** 17 | What happened? 18 | 19 | **Command** 20 | The exact command you were trying to run: 21 | 22 | ``` 23 | 24 | ``` 25 | 26 | Any output you get when running the command with the `-v` flag: 27 | 28 | ``` 29 | 30 | ``` 31 | 32 | **Environment (please complete the following information):** 33 | - [ ] Your operating system 34 | - [ ] Your Python version / distribution (`python3 --version` or `python --version`) 35 | - [ ] Your ffmpeg version (`ffmpeg -version`) 36 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: I want to suggest an idea for this project 4 | 5 | --- 6 | 7 | **:warning: Please read this carefully and edit the example responses! If you do not fill out this information, your feature request may be closed without comment.** 8 | 9 | **Is your feature request related to a problem? Please describe.** 10 | A clear and concise description of what the problem is. E.g. “I'm always frustrated when [...]” 11 | 12 | **Describe the solution you'd like** 13 | A clear and concise description of what you want to happen. 14 | 15 | **Describe alternatives you've considered** 16 | A clear and concise description of any alternative solutions or features you've considered. 17 | 18 | **Additional context** 19 | Add any other context or screenshots about the feature request here. 20 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Question/Support 3 | about: I am stuck with something and need help (not a bug or error) 4 | 5 | --- 6 | -------------------------------------------------------------------------------- /.github/workflows/python-package.yml: -------------------------------------------------------------------------------- 1 | name: Test Package 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | strategy: 13 | matrix: 14 | python-version: ["3.8", "3.9", "3.10", "3.11"] 15 | 16 | steps: 17 | - uses: actions/checkout@v3 18 | - name: Set up Python ${{ matrix.python-version }} 19 | uses: actions/setup-python@v4 20 | with: 21 | python-version: ${{ matrix.python-version }} 22 | - name: Install ffmpeg 23 | run: | 24 | sudo apt-get update -y 25 | sudo apt-get install -y ffmpeg 26 | - name: Install dependencies 27 | run: | 28 | python -m pip install --upgrade pip 29 | python -m pip install tox tox-gh-actions 30 | - name: Test with tox 31 | run: tox 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | *.py,cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | cover/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | .pybuilder/ 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | # For a library or package, you might want to ignore these files since the code is 87 | # intended to run in multiple environments; otherwise, check them in: 88 | # .python-version 89 | 90 | # pipenv 91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 | # install all needed dependencies. 95 | #Pipfile.lock 96 | 97 | # poetry 98 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 99 | # This is especially recommended for binary packages to ensure reproducibility, and is more 100 | # commonly ignored for libraries. 101 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 102 | #poetry.lock 103 | 104 | # pdm 105 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 106 | #pdm.lock 107 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 108 | # in version control. 109 | # https://pdm.fming.dev/#use-with-ide 110 | .pdm.toml 111 | 112 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 113 | __pypackages__/ 114 | 115 | # Celery stuff 116 | celerybeat-schedule 117 | celerybeat.pid 118 | 119 | # SageMath parsed files 120 | *.sage.py 121 | 122 | # Environments 123 | .env 124 | .venv 125 | env/ 126 | venv/ 127 | ENV/ 128 | env.bak/ 129 | venv.bak/ 130 | 131 | # Spyder project settings 132 | .spyderproject 133 | .spyproject 134 | 135 | # Rope project settings 136 | .ropeproject 137 | 138 | # mkdocs documentation 139 | /site 140 | 141 | # mypy 142 | .mypy_cache/ 143 | .dmypy.json 144 | dmypy.json 145 | 146 | # Pyre type checker 147 | .pyre/ 148 | 149 | # pytype static type analyzer 150 | .pytype/ 151 | 152 | # Cython debug symbols 153 | cython_debug/ 154 | 155 | # PyCharm 156 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 157 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 158 | # and can be added to the global gitignore or merged into this file. For a more nuclear 159 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 160 | #.idea/ 161 | 162 | .vscode 163 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | 4 | ## v1.1.2 (2024-11-14) 5 | 6 | * Fix: only add read_intervals option if needed. 7 | 8 | 9 | ## v1.1.1 (2024-11-04) 10 | 11 | * Abort on empty ffprobe output, addresses #13. 12 | 13 | * Update readme (contributors) 14 | 15 | * Docs: add GabrielChanzy as a contributor for code (#12) 16 | 17 | * docs: update README.md [skip ci] 18 | 19 | * docs: create .all-contributorsrc [skip ci] 20 | 21 | --------- 22 | 23 | 24 | ## v1.1.0 (2023-08-16) 25 | 26 | * Document inaccurate read-duration. 27 | 28 | * --read-length CLI option + some code suggestions (#11) 29 | 30 | * Added --read-length CLI option 31 | 32 | * Removed additional round for duration 33 | - duration is rounded at calculation & when creating BitrateStatsSummary 34 | 35 | * Edited logging in run_command function 36 | - removed verbose input parameter 37 | - added debug level log 38 | 39 | * fix first packet's pts bug with --read-length 40 | - calculates pts from next packet if value is missing 41 | 42 | * minor code touchups 43 | 44 | * Replaced read-length with read-start & read-end 45 | 46 | * fix read-duration type and add to README 47 | 48 | * fix first packet's duration bug 49 | - occurs with --read-duration) 50 | 51 | * edited for test case 52 | - added check for 1st packet's duration type 53 | 54 | --------- 55 | 56 | * Fix tests. 57 | 58 | 59 | ## v1.0.2 (2023-07-25) 60 | 61 | * Do not output chunk size when aggregation is GOP-based. 62 | 63 | * Fix plotting to always show seconds. 64 | 65 | 66 | ## v1.0.1 (2023-07-25) 67 | 68 | * Fix formatting for GOP based plots. 69 | 70 | 71 | ## v1.0.0 (2023-07-25) 72 | 73 | * Allow plotting results. 74 | 75 | 76 | ## v0.4.3 (2023-07-25) 77 | 78 | * Fix bug with keyframe detection. 79 | 80 | in some cases (when?), keyframes are not 'K_' but 'K__' 81 | 82 | * Add .vscode to gitignore. 83 | 84 | 85 | ## v0.4.2 (2023-07-25) 86 | 87 | * Fix frame order for bitrate calculation. 88 | 89 | ... in case PTS are unordered, bitrate may be negative for small chunk sizes 90 | 91 | 92 | ## v0.4.1 (2023-02-21) 93 | 94 | * Fix readme and add license file. 95 | 96 | * Add flake8 to tox, update GH actions. 97 | 98 | * Fix tox invocation. 99 | 100 | * Fix apt in CI. 101 | 102 | * Add tox and fix types. 103 | 104 | * Update gitignore. 105 | 106 | * Add mypy settings. 107 | 108 | * Remove stalebot. 109 | 110 | * Fix readme badge. 111 | 112 | * Fix changelog. 113 | 114 | * Fix setup script. 115 | 116 | * Update README. 117 | 118 | * Add github workflows. 119 | 120 | * Add note on old executable in readme. 121 | 122 | 123 | ## v0.4.0 (2023-01-01) 124 | 125 | * Add API, types and docs. 126 | 127 | * Bump python version, cleanup. 128 | 129 | 130 | ## v0.3.1 (2022-08-02) 131 | 132 | * Update python requirements. 133 | 134 | 135 | ## v0.3.0 (2022-08-02) 136 | 137 | * Add another console entry point. 138 | 139 | * Update python requirements. 140 | 141 | 142 | ## v0.2.3 (2022-01-09) 143 | 144 | * Remove delta-PTS calculation, replace with duration. 145 | 146 | this makes everything conceptually easier 147 | 148 | * Update badge link. 149 | 150 | 151 | ## v0.2.2 (2021-03-10) 152 | 153 | * Improve setup.py. 154 | 155 | * Remove release script. 156 | 157 | * Fix syntax error. 158 | 159 | * Format setup.py and switch to markdown. 160 | 161 | * Update badge URL. 162 | 163 | * Remove obsolete file. 164 | 165 | * Make test executable. 166 | 167 | 168 | ## v0.2.1 (2020-05-27) 169 | 170 | * Fix unit tests after program logic modification, fixes #7. 171 | 172 | * Change pip to pip3. 173 | 174 | * Fix description of duration calculation. 175 | 176 | 177 | ## v0.2.0 (2020-02-07) 178 | 179 | * Add py3.8 compat. 180 | 181 | * Add proper handling of PTS and duration/fps calculation. 182 | 183 | * Update release script. 184 | 185 | 186 | ## v0.1.3 (2020-01-16) 187 | 188 | * Fix casting problem, fixes #3. 189 | 190 | 191 | ## v0.1.2 (2020-01-14) 192 | 193 | * Rename changelog. 194 | 195 | * Update release script. 196 | 197 | 198 | ## v0.1.1 (2020-01-14) 199 | 200 | * Version bump to 0.1.1. 201 | 202 | * Add simple test suite. 203 | 204 | * Convert into float, fixes #3. 205 | 206 | * Add PyPI badge. 207 | 208 | 209 | ## v0.1 (2019-05-25) 210 | 211 | * Version bump to 0.1. 212 | 213 | * Make python package. 214 | 215 | * Fix examples in readme. 216 | 217 | * Update README.md. 218 | 219 | 220 | ## v0.0.2 (2019-04-19) 221 | 222 | * Version bump to 0.0.2. 223 | 224 | 225 | ## v0.0.1 (2019-04-19) 226 | 227 | * Initial commit. 228 | 229 | 230 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | ffmpeg_bitrate_stats, Copyright (c) 2019-2023 Werner Robitza 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FFmpeg Bitrate Stats 2 | 3 | [![All Contributors](https://img.shields.io/badge/all_contributors-1-orange.svg?style=flat-square)](#contributors-) 4 | 5 | 6 | [![PyPI version](https://img.shields.io/pypi/v/ffmpeg_bitrate_stats.svg)](https://pypi.org/project/ffmpeg_bitrate_stats) 7 | 8 | [![Python package](https://github.com/slhck/ffmpeg-bitrate-stats/actions/workflows/python-package.yml/badge.svg)](https://github.com/slhck/ffmpeg-bitrate-stats/actions/workflows/python-package.yml) 9 | 10 | Simple script for calculating bitrate statistics using FFmpeg. 11 | 12 | Author: Werner Robitza 13 | 14 | **Note:** Previous versions installed a `ffmpeg_bitrate_stats` executable. To harmonize it with other tools, now the executable is called `ffmpeg-bitrate-stats`. Please ensure you remove the old executable (e.g. run `which ffmpeg_bitrate_stats` and remove the file). 15 | 16 | Contents: 17 | 18 | - [Requirements](#requirements) 19 | - [Installation](#installation) 20 | - [Usage](#usage) 21 | - [Output](#output) 22 | - [Plotting](#plotting) 23 | - [API](#api) 24 | - [Contributors](#contributors) 25 | - [License](#license) 26 | 27 | ------ 28 | 29 | ## Requirements 30 | 31 | - Python 3.8 or higher 32 | - FFmpeg: 33 | - download a static build from [their website](http://ffmpeg.org/download.html) 34 | - put the `ffprobe` executable in your `$PATH` 35 | 36 | ## Installation 37 | 38 | ```bash 39 | pip3 install ffmpeg_bitrate_stats 40 | ``` 41 | 42 | Or clone this repository, then run the tool with `python -m ffmpeg_bitrate_stats` 43 | 44 | ## Usage 45 | 46 | The script outputs a bunch of bitrate statistics, including aggregations for pre-defined windows. These windows can either be time-based or GOP-based (for video streams). When choosing a time-based window, you can specify the size of the chunks in seconds. 47 | 48 | Output is to STDOUT so you can redirect that to a file or another script. 49 | 50 | See `ffmpeg-bitrate-stats -h`: 51 | 52 | ``` 53 | usage: __main__.py [-h] [-n] [-v] [-s {video,audio}] [-a {time,gop}] 54 | [-c CHUNK_SIZE] [-rs READ_START] [-rd READ_DURATION] 55 | [-of {json,csv}] [-p] [-pw PLOT_WIDTH] [-ph PLOT_HEIGHT] 56 | input 57 | 58 | ffmpeg_bitrate_stats v1.0.2 59 | 60 | positional arguments: 61 | input input file 62 | 63 | options: 64 | -h, --help show this help message and exit 65 | -n, --dry-run Do not run command, just show what would be done 66 | (default: False) 67 | -v, --verbose Show verbose output (default: False) 68 | -s {video,audio}, --stream-type {video,audio} 69 | Stream type to analyze (default: video) 70 | -a {time,gop}, --aggregation {time,gop} 71 | Window for aggregating statistics, either time-based 72 | (per-second) or per GOP (default: time) 73 | -c CHUNK_SIZE, --chunk-size CHUNK_SIZE 74 | Custom aggregation window size in seconds (default: 75 | 1.0) 76 | -rs READ_START, --read-start READ_START 77 | Time to wait before sampling video (in HH:MM:SS.msec 78 | or seconds) (default: None) 79 | -rd READ_DURATION, --read-duration READ_DURATION 80 | Duration for sampling stream (in HH:MM:SS.msec or 81 | seconds). Note that seeking is not accurate, see 82 | ffprobe documentation on '-read_intervals'. (default: 83 | None) 84 | -of {json,csv}, --output-format {json,csv} 85 | output in which format (default: json) 86 | -p, --plot Plot the bitrate over time (to STDERR) (default: 87 | False) 88 | -pw PLOT_WIDTH, --plot-width PLOT_WIDTH 89 | Plot width (default: 70) 90 | -ph PLOT_HEIGHT, --plot-height PLOT_HEIGHT 91 | Plot height (default: 18) 92 | ``` 93 | 94 | ## Output 95 | 96 | The output can be JSON, which includes individual fields for each chunk, or CSV, which repeats each line for each chunk. The CSV adheres to the “tidy” data concept, so it's a little redundant. 97 | 98 | Rates are given in kilobit per second, using SI prefixes (i.e., kilo = 1000). 99 | 100 | Explanation of the fields: 101 | 102 | - `input_file`: Path to the input file 103 | - `stream_type`: Type of stream used (video, audio) 104 | - `avg_fps`: Average FPS (number of frames divided by duration) 105 | - `num_frames`: Number of frames 106 | - `avg_bitrate`: Average bitrate 107 | - `avg_bitrate_over_chunks`: Average bitrate calculated over the chunks 108 | - `max_bitrate`: Maximum bitrate calculated over the chunks 109 | - `min_bitrate`: Minimum bitrate calculated over the chunks 110 | - `max_bitrate_factor`: Relation between peak and average 111 | - `bitrate_per_chunk`: Individual bitrates for each chunk 112 | - `aggregation`: Type of aggregation used 113 | - `chunk_size`: Size of the chunk (when aggregation is "time") 114 | - `duration`: Total duration of the stream. It is the sum of all frame durations, where each frame's duration is either based on `duration_time` field in ffmpeg, or the difference between the current and previous frame's PTS. 115 | 116 | JSON example: 117 | 118 | ```bash 119 | ffmpeg-bitrate-stats -a time -c 30 -of json BigBuckBunny.mp4 120 | ``` 121 | 122 | This returns: 123 | ```json 124 | { 125 | "input_file": "BigBuckBunny.mp4", 126 | "stream_type": "video", 127 | "avg_fps": 60.002, 128 | "num_frames": 38072, 129 | "avg_bitrate": 8002.859, 130 | "avg_bitrate_over_chunks": 7849.263, 131 | "max_bitrate": 14565.117, 132 | "min_bitrate": 3876.533, 133 | "max_bitrate_factor": 1.82, 134 | "bitrate_per_chunk": [ 135 | 8960.89, 136 | 8036.678, 137 | 6099.959, 138 | 4247.879, 139 | 7276.979, 140 | 5738.383, 141 | 7740.339, 142 | 7881.705, 143 | 7572.594, 144 | 8387.719, 145 | 9634.343, 146 | 9939.488, 147 | 9365.104, 148 | 5061.071, 149 | 14565.117, 150 | 9725.483, 151 | 4573.873, 152 | 7765.041, 153 | 9796.135, 154 | 12524.024, 155 | 3876.533, 156 | 3914.455 157 | ], 158 | "aggregation": "time", 159 | "chunk_size": 30.0, 160 | "duration": 634.517 161 | } 162 | ``` 163 | 164 | CSV example: 165 | 166 | ``` 167 | ➜ ffmpeg-bitrate-stats -a time -c 30 -of csv BigBuckBunny.mp4 168 | input_file,chunk_index,stream_type,avg_fps,num_frames,avg_bitrate,avg_bitrate_over_chunks,max_bitrate,min_bitrate,max_bitrate_factor,bitrate_per_chunk,aggregation,chunk_size,duration 169 | BigBuckBunny.mp4,0,video,60.002,38072,8002.859,7849.263,14565.117,3876.533,1.82,8960.89,time,30.0,634.517 170 | BigBuckBunny.mp4,1,video,60.002,38072,8002.859,7849.263,14565.117,3876.533,1.82,8036.678,time,30.0,634.517 171 | BigBuckBunny.mp4,2,video,60.002,38072,8002.859,7849.263,14565.117,3876.533,1.82,6099.959,time,30.0,634.517 172 | BigBuckBunny.mp4,3,video,60.002,38072,8002.859,7849.263,14565.117,3876.533,1.82,4247.879,time,30.0,634.517 173 | BigBuckBunny.mp4,4,video,60.002,38072,8002.859,7849.263,14565.117,3876.533,1.82,7276.979,time,30.0,634.517 174 | BigBuckBunny.mp4,5,video,60.002,38072,8002.859,7849.263,14565.117,3876.533,1.82,5738.383,time,30.0,634.517 175 | BigBuckBunny.mp4,6,video,60.002,38072,8002.859,7849.263,14565.117,3876.533,1.82,7740.339,time,30.0,634.517 176 | BigBuckBunny.mp4,7,video,60.002,38072,8002.859,7849.263,14565.117,3876.533,1.82,7881.705,time,30.0,634.517 177 | BigBuckBunny.mp4,8,video,60.002,38072,8002.859,7849.263,14565.117,3876.533,1.82,7572.594,time,30.0,634.517 178 | BigBuckBunny.mp4,9,video,60.002,38072,8002.859,7849.263,14565.117,3876.533,1.82,8387.719,time,30.0,634.517 179 | BigBuckBunny.mp4,10,video,60.002,38072,8002.859,7849.263,14565.117,3876.533,1.82,9634.343,time,30.0,634.517 180 | BigBuckBunny.mp4,11,video,60.002,38072,8002.859,7849.263,14565.117,3876.533,1.82,9939.488,time,30.0,634.517 181 | BigBuckBunny.mp4,12,video,60.002,38072,8002.859,7849.263,14565.117,3876.533,1.82,9365.104,time,30.0,634.517 182 | BigBuckBunny.mp4,13,video,60.002,38072,8002.859,7849.263,14565.117,3876.533,1.82,5061.071,time,30.0,634.517 183 | BigBuckBunny.mp4,14,video,60.002,38072,8002.859,7849.263,14565.117,3876.533,1.82,14565.117,time,30.0,634.517 184 | BigBuckBunny.mp4,15,video,60.002,38072,8002.859,7849.263,14565.117,3876.533,1.82,9725.483,time,30.0,634.517 185 | BigBuckBunny.mp4,16,video,60.002,38072,8002.859,7849.263,14565.117,3876.533,1.82,4573.873,time,30.0,634.517 186 | BigBuckBunny.mp4,17,video,60.002,38072,8002.859,7849.263,14565.117,3876.533,1.82,7765.041,time,30.0,634.517 187 | BigBuckBunny.mp4,18,video,60.002,38072,8002.859,7849.263,14565.117,3876.533,1.82,9796.135,time,30.0,634.517 188 | BigBuckBunny.mp4,19,video,60.002,38072,8002.859,7849.263,14565.117,3876.533,1.82,12524.024,time,30.0,634.517 189 | BigBuckBunny.mp4,20,video,60.002,38072,8002.859,7849.263,14565.117,3876.533,1.82,3876.533,time,30.0,634.517 190 | BigBuckBunny.mp4,21,video,60.002,38072,8002.859,7849.263,14565.117,3876.533,1.82,3914.455,time,30.0,634.517 191 | ``` 192 | 193 | ## Plotting 194 | 195 | To enable plots, pass the `-p` or `--plot` flag. This will plot the bitrate over time to STDERR. You can redirect this to a file, or pipe it to another program. Or you can disable STDOUT output with `>/dev/null` to only see the plot: 196 | 197 | ```bash 198 | ffmpeg-bitrate-stats -a time -c 30 -p BigBuckBunny.mp4 >/dev/null 199 | ``` 200 | 201 | This might output a plot like this: 202 | 203 | ```console 204 | 7474.000 | 205 | 6975.733 | ⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡎⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ 206 | 6477.467 | ⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⠁⢱⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ 207 | 5979.200 | ⡇⠀⠀⠀⠀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡎⠀⠈⡆⠀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ 208 | 5480.933 | ⡧⡀⠀⠀⢰⢱⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⠁⠀⠀⠱⠊⠱⡀⠀⠀⠀⠀⢀⠤⡀⠀⠀⠀⠀⠀⠀⢀⡄⠀⠀⢠⠊⠈⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ 209 | 4982.667 | ⡇⠈⢆⠀⡜⠀⢣⠀⠀⠀⠀⠀⠀⡠⠒⠙⡄⠀⠀⡀⠀⠀⢀⡀⠀⢠⢢⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡎⠀⠀⠀⠀⠀⠀⢣⠀⢀⣀⠤⠊⠀⠈⠑⠢⢄⠀⠀⢠⠊⠘⡄⡰⠁⠀⠀⠈⢢⠀⠀⠀⣀⠤⠤⡀⠀⠀⠀⠀ 210 | 4484.400 | ⡇⠀⠈⢶⠁⠀⠈⠦⣀⠀⠀⠀⡔⠁⠀⠀⠱⡀⢰⠙⡄⢀⠎⠈⠒⠁⠀⠱⡀⠀⠀⠀⢠⠓⡄⢀⠤⡀⢰⠁⠀⠀⠀⠀⠀⠀⠀⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀⠉⠉⠁⠀⠀⠘⠁⠀⠀⠀⠀⠀⠑⠒⠊⠀⠀⠀⠈⠢⠤⡄⠀ 211 | 3986.133 | ⡇⠀⠀⠀⠀⠀⠀⠀⠈⢢⠀⡸⠀⠀⠀⠀⠀⢣⠃⠀⠘⠎⠀⠀⠀⠀⠀⠀⠈⢆⡀⠀⡎⠀⠈⠁⠀⠱⡎⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢱⠀ 212 | 3487.867 | ⡇⠀⠀⠀⠀⠀⠀⠀⠀⠈⢢⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠚⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⡄ 213 | 2989.600 | ⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇ 214 | 2491.333 | ⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸ 215 | 1993.067 | ⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈ 216 | 1494.800 | ⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ 217 | 996.533 | ⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ 218 | 498.267 | ⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ 219 | 0.000 | ⣇⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀ 220 | -----------|-|---------|---------|---------|---------|---------|---------|---------|---------|-> (Time (s)) 221 | | 0.000 5.760 11.520 17.280 23.040 28.800 34.560 40.320 46.080 222 | ``` 223 | 224 | ## API 225 | 226 | The program exposes an API that you can use yourself: 227 | 228 | ```python 229 | from ffmpeg_bitrate_stats import BitrateStats 230 | 231 | ffbs = BitrateStats("path/to/ref") 232 | ffbs.calculate_statistics() 233 | ffbs.print_statistics() 234 | ``` 235 | 236 | For more usage please read [the docs](https://htmlpreview.github.io/?https://github.com/slhck/ffmpeg-bitrate-stats/blob/master/docs/ffmpeg_bitrate_stats.html). 237 | 238 | ## Contributors 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 |
GabrielChanzy
GabrielChanzy

💻
250 | 251 | 252 | 253 | 254 | 255 | 256 | ## License 257 | 258 | ffmpeg_bitrate_stats, Copyright (c) 2019-2023 Werner Robitza 259 | 260 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 261 | 262 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 263 | 264 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 265 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /docs/search.js: -------------------------------------------------------------------------------- 1 | window.pdocSearch = (function(){ 2 | /** elasticlunr - http://weixsong.github.io * Copyright (C) 2017 Oliver Nightingale * Copyright (C) 2017 Wei Song * MIT Licensed */!function(){function e(e){if(null===e||"object"!=typeof e)return e;var t=e.constructor();for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t}var t=function(e){var n=new t.Index;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),e&&e.call(n,n),n};t.version="0.9.5",lunr=t,t.utils={},t.utils.warn=function(e){return function(t){e.console&&console.warn&&console.warn(t)}}(this),t.utils.toString=function(e){return void 0===e||null===e?"":e.toString()},t.EventEmitter=function(){this.events={}},t.EventEmitter.prototype.addListener=function(){var e=Array.prototype.slice.call(arguments),t=e.pop(),n=e;if("function"!=typeof t)throw new TypeError("last argument must be a function");n.forEach(function(e){this.hasHandler(e)||(this.events[e]=[]),this.events[e].push(t)},this)},t.EventEmitter.prototype.removeListener=function(e,t){if(this.hasHandler(e)){var n=this.events[e].indexOf(t);-1!==n&&(this.events[e].splice(n,1),0==this.events[e].length&&delete this.events[e])}},t.EventEmitter.prototype.emit=function(e){if(this.hasHandler(e)){var t=Array.prototype.slice.call(arguments,1);this.events[e].forEach(function(e){e.apply(void 0,t)},this)}},t.EventEmitter.prototype.hasHandler=function(e){return e in this.events},t.tokenizer=function(e){if(!arguments.length||null===e||void 0===e)return[];if(Array.isArray(e)){var n=e.filter(function(e){return null===e||void 0===e?!1:!0});n=n.map(function(e){return t.utils.toString(e).toLowerCase()});var i=[];return n.forEach(function(e){var n=e.split(t.tokenizer.seperator);i=i.concat(n)},this),i}return e.toString().trim().toLowerCase().split(t.tokenizer.seperator)},t.tokenizer.defaultSeperator=/[\s\-]+/,t.tokenizer.seperator=t.tokenizer.defaultSeperator,t.tokenizer.setSeperator=function(e){null!==e&&void 0!==e&&"object"==typeof e&&(t.tokenizer.seperator=e)},t.tokenizer.resetSeperator=function(){t.tokenizer.seperator=t.tokenizer.defaultSeperator},t.tokenizer.getSeperator=function(){return t.tokenizer.seperator},t.Pipeline=function(){this._queue=[]},t.Pipeline.registeredFunctions={},t.Pipeline.registerFunction=function(e,n){n in t.Pipeline.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[n]=e},t.Pipeline.getRegisteredFunction=function(e){return e in t.Pipeline.registeredFunctions!=!0?null:t.Pipeline.registeredFunctions[e]},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(e){var i=t.Pipeline.getRegisteredFunction(e);if(!i)throw new Error("Cannot load un-registered function: "+e);n.add(i)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(e){t.Pipeline.warnIfFunctionNotRegistered(e),this._queue.push(e)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i+1,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i,0,n)},t.Pipeline.prototype.remove=function(e){var t=this._queue.indexOf(e);-1!==t&&this._queue.splice(t,1)},t.Pipeline.prototype.run=function(e){for(var t=[],n=e.length,i=this._queue.length,o=0;n>o;o++){for(var r=e[o],s=0;i>s&&(r=this._queue[s](r,o,e),void 0!==r&&null!==r);s++);void 0!==r&&null!==r&&t.push(r)}return t},t.Pipeline.prototype.reset=function(){this._queue=[]},t.Pipeline.prototype.get=function(){return this._queue},t.Pipeline.prototype.toJSON=function(){return this._queue.map(function(e){return t.Pipeline.warnIfFunctionNotRegistered(e),e.label})},t.Index=function(){this._fields=[],this._ref="id",this.pipeline=new t.Pipeline,this.documentStore=new t.DocumentStore,this.index={},this.eventEmitter=new t.EventEmitter,this._idfCache={},this.on("add","remove","update",function(){this._idfCache={}}.bind(this))},t.Index.prototype.on=function(){var e=Array.prototype.slice.call(arguments);return this.eventEmitter.addListener.apply(this.eventEmitter,e)},t.Index.prototype.off=function(e,t){return this.eventEmitter.removeListener(e,t)},t.Index.load=function(e){e.version!==t.version&&t.utils.warn("version mismatch: current "+t.version+" importing "+e.version);var n=new this;n._fields=e.fields,n._ref=e.ref,n.documentStore=t.DocumentStore.load(e.documentStore),n.pipeline=t.Pipeline.load(e.pipeline),n.index={};for(var i in e.index)n.index[i]=t.InvertedIndex.load(e.index[i]);return n},t.Index.prototype.addField=function(e){return this._fields.push(e),this.index[e]=new t.InvertedIndex,this},t.Index.prototype.setRef=function(e){return this._ref=e,this},t.Index.prototype.saveDocument=function(e){return this.documentStore=new t.DocumentStore(e),this},t.Index.prototype.addDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.addDoc(i,e),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));this.documentStore.addFieldLength(i,n,o.length);var r={};o.forEach(function(e){e in r?r[e]+=1:r[e]=1},this);for(var s in r){var u=r[s];u=Math.sqrt(u),this.index[n].addToken(s,{ref:i,tf:u})}},this),n&&this.eventEmitter.emit("add",e,this)}},t.Index.prototype.removeDocByRef=function(e){if(e&&this.documentStore.isDocStored()!==!1&&this.documentStore.hasDoc(e)){var t=this.documentStore.getDoc(e);this.removeDoc(t,!1)}},t.Index.prototype.removeDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.hasDoc(i)&&(this.documentStore.removeDoc(i),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));o.forEach(function(e){this.index[n].removeToken(e,i)},this)},this),n&&this.eventEmitter.emit("remove",e,this))}},t.Index.prototype.updateDoc=function(e,t){var t=void 0===t?!0:t;this.removeDocByRef(e[this._ref],!1),this.addDoc(e,!1),t&&this.eventEmitter.emit("update",e,this)},t.Index.prototype.idf=function(e,t){var n="@"+t+"/"+e;if(Object.prototype.hasOwnProperty.call(this._idfCache,n))return this._idfCache[n];var i=this.index[t].getDocFreq(e),o=1+Math.log(this.documentStore.length/(i+1));return this._idfCache[n]=o,o},t.Index.prototype.getFields=function(){return this._fields.slice()},t.Index.prototype.search=function(e,n){if(!e)return[];e="string"==typeof e?{any:e}:JSON.parse(JSON.stringify(e));var i=null;null!=n&&(i=JSON.stringify(n));for(var o=new t.Configuration(i,this.getFields()).get(),r={},s=Object.keys(e),u=0;u0&&t.push(e);for(var i in n)"docs"!==i&&"df"!==i&&this.expandToken(e+i,t,n[i]);return t},t.InvertedIndex.prototype.toJSON=function(){return{root:this.root}},t.Configuration=function(e,n){var e=e||"";if(void 0==n||null==n)throw new Error("fields should not be null");this.config={};var i;try{i=JSON.parse(e),this.buildUserConfig(i,n)}catch(o){t.utils.warn("user configuration parse failed, will use default configuration"),this.buildDefaultConfig(n)}},t.Configuration.prototype.buildDefaultConfig=function(e){this.reset(),e.forEach(function(e){this.config[e]={boost:1,bool:"OR",expand:!1}},this)},t.Configuration.prototype.buildUserConfig=function(e,n){var i="OR",o=!1;if(this.reset(),"bool"in e&&(i=e.bool||i),"expand"in e&&(o=e.expand||o),"fields"in e)for(var r in e.fields)if(n.indexOf(r)>-1){var s=e.fields[r],u=o;void 0!=s.expand&&(u=s.expand),this.config[r]={boost:s.boost||0===s.boost?s.boost:1,bool:s.bool||i,expand:u}}else t.utils.warn("field name in user configuration not found in index instance fields");else this.addAllFields2UserConfig(i,o,n)},t.Configuration.prototype.addAllFields2UserConfig=function(e,t,n){n.forEach(function(n){this.config[n]={boost:1,bool:e,expand:t}},this)},t.Configuration.prototype.get=function(){return this.config},t.Configuration.prototype.reset=function(){this.config={}},lunr.SortedSet=function(){this.length=0,this.elements=[]},lunr.SortedSet.load=function(e){var t=new this;return t.elements=e,t.length=e.length,t},lunr.SortedSet.prototype.add=function(){var e,t;for(e=0;e1;){if(r===e)return o;e>r&&(t=o),r>e&&(n=o),i=n-t,o=t+Math.floor(i/2),r=this.elements[o]}return r===e?o:-1},lunr.SortedSet.prototype.locationFor=function(e){for(var t=0,n=this.elements.length,i=n-t,o=t+Math.floor(i/2),r=this.elements[o];i>1;)e>r&&(t=o),r>e&&(n=o),i=n-t,o=t+Math.floor(i/2),r=this.elements[o];return r>e?o:e>r?o+1:void 0},lunr.SortedSet.prototype.intersect=function(e){for(var t=new lunr.SortedSet,n=0,i=0,o=this.length,r=e.length,s=this.elements,u=e.elements;;){if(n>o-1||i>r-1)break;s[n]!==u[i]?s[n]u[i]&&i++:(t.add(s[n]),n++,i++)}return t},lunr.SortedSet.prototype.clone=function(){var e=new lunr.SortedSet;return e.elements=this.toArray(),e.length=e.elements.length,e},lunr.SortedSet.prototype.union=function(e){var t,n,i;this.length>=e.length?(t=this,n=e):(t=e,n=this),i=t.clone();for(var o=0,r=n.toArray();o

\n"}, "ffmpeg_bitrate_stats.BitrateStats": {"fullname": "ffmpeg_bitrate_stats.BitrateStats", "modulename": "ffmpeg_bitrate_stats", "qualname": "BitrateStats", "kind": "class", "doc": "

Initialize the BitrateStats class.

\n\n
Arguments:
\n\n
    \n
  • input_file (str): Path to the input file
  • \n
  • stream_type (str, optional): Stream type (audio/video). Defaults to \"video\".
  • \n
  • aggregation (str, optional): Aggregation type (time/gop). Defaults to \"time\".
  • \n
  • chunk_size (int, optional): Chunk size. Defaults to 1.
  • \n
  • read_start (str, optional): Start time for reading in HH:MM:SS.msec or seconds. Defaults to None.
  • \n
  • read_duration (str, optional): Duration for reading in HH:MM:SS.msec or seconds. Defaults to None.
  • \n
  • dry_run (bool, optional): Dry run. Defaults to False.
  • \n
\n"}, "ffmpeg_bitrate_stats.BitrateStats.__init__": {"fullname": "ffmpeg_bitrate_stats.BitrateStats.__init__", "modulename": "ffmpeg_bitrate_stats", "qualname": "BitrateStats.__init__", "kind": "function", "doc": "

\n", "signature": "(\tinput_file: str,\tstream_type: Literal['audio', 'video'] = 'video',\taggregation: Literal['time', 'gop'] = 'time',\tchunk_size: int = 1,\tread_start: Optional[str] = None,\tread_duration: Optional[str] = None,\tdry_run: bool = False)"}, "ffmpeg_bitrate_stats.BitrateStats.input_file": {"fullname": "ffmpeg_bitrate_stats.BitrateStats.input_file", "modulename": "ffmpeg_bitrate_stats", "qualname": "BitrateStats.input_file", "kind": "variable", "doc": "

\n"}, "ffmpeg_bitrate_stats.BitrateStats.stream_type": {"fullname": "ffmpeg_bitrate_stats.BitrateStats.stream_type", "modulename": "ffmpeg_bitrate_stats", "qualname": "BitrateStats.stream_type", "kind": "variable", "doc": "

\n", "annotation": ": Literal['audio', 'video']"}, "ffmpeg_bitrate_stats.BitrateStats.aggregation": {"fullname": "ffmpeg_bitrate_stats.BitrateStats.aggregation", "modulename": "ffmpeg_bitrate_stats", "qualname": "BitrateStats.aggregation", "kind": "variable", "doc": "

\n", "annotation": ": Literal['time', 'gop']"}, "ffmpeg_bitrate_stats.BitrateStats.chunk_size": {"fullname": "ffmpeg_bitrate_stats.BitrateStats.chunk_size", "modulename": "ffmpeg_bitrate_stats", "qualname": "BitrateStats.chunk_size", "kind": "variable", "doc": "

\n"}, "ffmpeg_bitrate_stats.BitrateStats.read_length": {"fullname": "ffmpeg_bitrate_stats.BitrateStats.read_length", "modulename": "ffmpeg_bitrate_stats", "qualname": "BitrateStats.read_length", "kind": "variable", "doc": "

\n", "annotation": ": Optional[str]"}, "ffmpeg_bitrate_stats.BitrateStats.dry_run": {"fullname": "ffmpeg_bitrate_stats.BitrateStats.dry_run", "modulename": "ffmpeg_bitrate_stats", "qualname": "BitrateStats.dry_run", "kind": "variable", "doc": "

\n"}, "ffmpeg_bitrate_stats.BitrateStats.duration": {"fullname": "ffmpeg_bitrate_stats.BitrateStats.duration", "modulename": "ffmpeg_bitrate_stats", "qualname": "BitrateStats.duration", "kind": "variable", "doc": "

\n", "annotation": ": float"}, "ffmpeg_bitrate_stats.BitrateStats.fps": {"fullname": "ffmpeg_bitrate_stats.BitrateStats.fps", "modulename": "ffmpeg_bitrate_stats", "qualname": "BitrateStats.fps", "kind": "variable", "doc": "

\n", "annotation": ": float"}, "ffmpeg_bitrate_stats.BitrateStats.max_bitrate": {"fullname": "ffmpeg_bitrate_stats.BitrateStats.max_bitrate", "modulename": "ffmpeg_bitrate_stats", "qualname": "BitrateStats.max_bitrate", "kind": "variable", "doc": "

\n", "annotation": ": float"}, "ffmpeg_bitrate_stats.BitrateStats.min_bitrate": {"fullname": "ffmpeg_bitrate_stats.BitrateStats.min_bitrate", "modulename": "ffmpeg_bitrate_stats", "qualname": "BitrateStats.min_bitrate", "kind": "variable", "doc": "

\n", "annotation": ": float"}, "ffmpeg_bitrate_stats.BitrateStats.moving_avg_bitrate": {"fullname": "ffmpeg_bitrate_stats.BitrateStats.moving_avg_bitrate", "modulename": "ffmpeg_bitrate_stats", "qualname": "BitrateStats.moving_avg_bitrate", "kind": "variable", "doc": "

\n", "annotation": ": list[float]"}, "ffmpeg_bitrate_stats.BitrateStats.frames": {"fullname": "ffmpeg_bitrate_stats.BitrateStats.frames", "modulename": "ffmpeg_bitrate_stats", "qualname": "BitrateStats.frames", "kind": "variable", "doc": "

\n", "annotation": ": list[ffmpeg_bitrate_stats.bitrate_stats.FrameEntry]"}, "ffmpeg_bitrate_stats.BitrateStats.bitrate_stats": {"fullname": "ffmpeg_bitrate_stats.BitrateStats.bitrate_stats", "modulename": "ffmpeg_bitrate_stats", "qualname": "BitrateStats.bitrate_stats", "kind": "variable", "doc": "

\n", "annotation": ": ffmpeg_bitrate_stats.bitrate_stats.BitrateStatsSummary | None"}, "ffmpeg_bitrate_stats.BitrateStats.rounding_factor": {"fullname": "ffmpeg_bitrate_stats.BitrateStats.rounding_factor", "modulename": "ffmpeg_bitrate_stats", "qualname": "BitrateStats.rounding_factor", "kind": "variable", "doc": "

\n", "annotation": ": int"}, "ffmpeg_bitrate_stats.BitrateStats.calculate_statistics": {"fullname": "ffmpeg_bitrate_stats.BitrateStats.calculate_statistics", "modulename": "ffmpeg_bitrate_stats", "qualname": "BitrateStats.calculate_statistics", "kind": "function", "doc": "

Calculate the bitrate statistics.

\n\n
Raises:
\n\n
    \n
  • RuntimeError: If an error occurred.
  • \n
\n\n
Returns:
\n\n
\n

dict: The bitrate statistics summary.

\n
\n", "signature": "(self) -> ffmpeg_bitrate_stats.bitrate_stats.BitrateStatsSummary:", "funcdef": "def"}, "ffmpeg_bitrate_stats.BitrateStats.print_statistics": {"fullname": "ffmpeg_bitrate_stats.BitrateStats.print_statistics", "modulename": "ffmpeg_bitrate_stats", "qualname": "BitrateStats.print_statistics", "kind": "function", "doc": "

Print the statistics in the specified format to stdout.

\n\n
Arguments:
\n\n
    \n
  • output_format: The format to print the statistics in (csv, json)
  • \n
\n\n
Raises:
\n\n
    \n
  • ValueError: If the output format is invalid
  • \n
\n", "signature": "(self, output_format: Literal['csv', 'json']) -> None:", "funcdef": "def"}, "ffmpeg_bitrate_stats.BitrateStats.get_csv": {"fullname": "ffmpeg_bitrate_stats.BitrateStats.get_csv", "modulename": "ffmpeg_bitrate_stats", "qualname": "BitrateStats.get_csv", "kind": "function", "doc": "

Get the bitrate statistics as a CSV string.

\n\n
Raises:
\n\n
    \n
  • RuntimeError: If no bitrate statistics are available
  • \n
\n\n
Returns:
\n\n
\n

str: The bitrate statistics as a CSV string

\n
\n", "signature": "(self) -> str:", "funcdef": "def"}, "ffmpeg_bitrate_stats.BitrateStats.get_json": {"fullname": "ffmpeg_bitrate_stats.BitrateStats.get_json", "modulename": "ffmpeg_bitrate_stats", "qualname": "BitrateStats.get_json", "kind": "function", "doc": "

Get the bitrate statistics as a JSON string.

\n\n
Raises:
\n\n
    \n
  • RuntimeError: If no bitrate statistics are available
  • \n
\n\n
Returns:
\n\n
\n

str: The bitrate statistics as a JSON string

\n
\n", "signature": "(self) -> str:", "funcdef": "def"}, "ffmpeg_bitrate_stats.BitrateStats.plot": {"fullname": "ffmpeg_bitrate_stats.BitrateStats.plot", "modulename": "ffmpeg_bitrate_stats", "qualname": "BitrateStats.plot", "kind": "function", "doc": "

Plot the bitrate over time to STDERR.

\n\n
Arguments:
\n\n
    \n
  • width (int, optional): Width of the plot. Defaults to 80.
  • \n
  • height (int, optional): Height of the plot. Defaults to 30.
  • \n
\n", "signature": "(self, width: int = 80, height: int = 30) -> None:", "funcdef": "def"}, "ffmpeg_bitrate_stats.BitrateStatsSummary": {"fullname": "ffmpeg_bitrate_stats.BitrateStatsSummary", "modulename": "ffmpeg_bitrate_stats", "qualname": "BitrateStatsSummary", "kind": "class", "doc": "

\n", "bases": "typing.TypedDict"}, "ffmpeg_bitrate_stats.BitrateStatsSummary.input_file": {"fullname": "ffmpeg_bitrate_stats.BitrateStatsSummary.input_file", "modulename": "ffmpeg_bitrate_stats", "qualname": "BitrateStatsSummary.input_file", "kind": "variable", "doc": "

The input file.

\n", "annotation": ": str"}, "ffmpeg_bitrate_stats.BitrateStatsSummary.stream_type": {"fullname": "ffmpeg_bitrate_stats.BitrateStatsSummary.stream_type", "modulename": "ffmpeg_bitrate_stats", "qualname": "BitrateStatsSummary.stream_type", "kind": "variable", "doc": "

The stream type (audio/video).

\n", "annotation": ": Literal['audio', 'video']"}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_fps": {"fullname": "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_fps", "modulename": "ffmpeg_bitrate_stats", "qualname": "BitrateStatsSummary.avg_fps", "kind": "variable", "doc": "

The average FPS.

\n", "annotation": ": float"}, "ffmpeg_bitrate_stats.BitrateStatsSummary.num_frames": {"fullname": "ffmpeg_bitrate_stats.BitrateStatsSummary.num_frames", "modulename": "ffmpeg_bitrate_stats", "qualname": "BitrateStatsSummary.num_frames", "kind": "variable", "doc": "

The number of frames.

\n", "annotation": ": int"}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate": {"fullname": "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate", "modulename": "ffmpeg_bitrate_stats", "qualname": "BitrateStatsSummary.avg_bitrate", "kind": "variable", "doc": "

The average bitrate in kbit/s.

\n", "annotation": ": float"}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate_over_chunks": {"fullname": "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate_over_chunks", "modulename": "ffmpeg_bitrate_stats", "qualname": "BitrateStatsSummary.avg_bitrate_over_chunks", "kind": "variable", "doc": "

The average bitrate in kbit/s over chunks.

\n", "annotation": ": float"}, "ffmpeg_bitrate_stats.BitrateStatsSummary.max_bitrate": {"fullname": "ffmpeg_bitrate_stats.BitrateStatsSummary.max_bitrate", "modulename": "ffmpeg_bitrate_stats", "qualname": "BitrateStatsSummary.max_bitrate", "kind": "variable", "doc": "

The maximum bitrate in kbit/s.

\n", "annotation": ": float"}, "ffmpeg_bitrate_stats.BitrateStatsSummary.min_bitrate": {"fullname": "ffmpeg_bitrate_stats.BitrateStatsSummary.min_bitrate", "modulename": "ffmpeg_bitrate_stats", "qualname": "BitrateStatsSummary.min_bitrate", "kind": "variable", "doc": "

The minimum bitrate in kbit/s.

\n", "annotation": ": float"}, "ffmpeg_bitrate_stats.BitrateStatsSummary.max_bitrate_factor": {"fullname": "ffmpeg_bitrate_stats.BitrateStatsSummary.max_bitrate_factor", "modulename": "ffmpeg_bitrate_stats", "qualname": "BitrateStatsSummary.max_bitrate_factor", "kind": "variable", "doc": "

Relation between peak and average.

\n", "annotation": ": float"}, "ffmpeg_bitrate_stats.BitrateStatsSummary.bitrate_per_chunk": {"fullname": "ffmpeg_bitrate_stats.BitrateStatsSummary.bitrate_per_chunk", "modulename": "ffmpeg_bitrate_stats", "qualname": "BitrateStatsSummary.bitrate_per_chunk", "kind": "variable", "doc": "

The bitrate per chunk in kbit/s.

\n", "annotation": ": list[float]"}, "ffmpeg_bitrate_stats.BitrateStatsSummary.aggregation": {"fullname": "ffmpeg_bitrate_stats.BitrateStatsSummary.aggregation", "modulename": "ffmpeg_bitrate_stats", "qualname": "BitrateStatsSummary.aggregation", "kind": "variable", "doc": "

The aggregation type (time/chunks).

\n", "annotation": ": Literal['time', 'gop']"}, "ffmpeg_bitrate_stats.BitrateStatsSummary.chunk_size": {"fullname": "ffmpeg_bitrate_stats.BitrateStatsSummary.chunk_size", "modulename": "ffmpeg_bitrate_stats", "qualname": "BitrateStatsSummary.chunk_size", "kind": "variable", "doc": "

The chunk size in seconds.

\n", "annotation": ": Optional[int]"}, "ffmpeg_bitrate_stats.BitrateStatsSummary.duration": {"fullname": "ffmpeg_bitrate_stats.BitrateStatsSummary.duration", "modulename": "ffmpeg_bitrate_stats", "qualname": "BitrateStatsSummary.duration", "kind": "variable", "doc": "

The duration in seconds.

\n", "annotation": ": float"}, "ffmpeg_bitrate_stats.run_command": {"fullname": "ffmpeg_bitrate_stats.run_command", "modulename": "ffmpeg_bitrate_stats", "qualname": "run_command", "kind": "function", "doc": "

Run a command directly

\n", "signature": "(\tcmd: List[str],\tdry_run: bool = False) -> tuple[str, str] | tuple[None, None]:", "funcdef": "def"}}, "docInfo": {"ffmpeg_bitrate_stats": {"qualname": 0, "fullname": 3, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "ffmpeg_bitrate_stats.BitrateStats": {"qualname": 1, "fullname": 4, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 131}, "ffmpeg_bitrate_stats.BitrateStats.__init__": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 189, "bases": 0, "doc": 3}, "ffmpeg_bitrate_stats.BitrateStats.input_file": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "ffmpeg_bitrate_stats.BitrateStats.stream_type": {"qualname": 3, "fullname": 6, "annotation": 9, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "ffmpeg_bitrate_stats.BitrateStats.aggregation": {"qualname": 2, "fullname": 5, "annotation": 9, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "ffmpeg_bitrate_stats.BitrateStats.chunk_size": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "ffmpeg_bitrate_stats.BitrateStats.read_length": {"qualname": 3, "fullname": 6, "annotation": 2, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "ffmpeg_bitrate_stats.BitrateStats.dry_run": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "ffmpeg_bitrate_stats.BitrateStats.duration": {"qualname": 2, "fullname": 5, "annotation": 2, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "ffmpeg_bitrate_stats.BitrateStats.fps": {"qualname": 2, "fullname": 5, "annotation": 2, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "ffmpeg_bitrate_stats.BitrateStats.max_bitrate": {"qualname": 3, "fullname": 6, "annotation": 2, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "ffmpeg_bitrate_stats.BitrateStats.min_bitrate": {"qualname": 3, "fullname": 6, "annotation": 2, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "ffmpeg_bitrate_stats.BitrateStats.moving_avg_bitrate": {"qualname": 4, "fullname": 7, "annotation": 2, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "ffmpeg_bitrate_stats.BitrateStats.frames": {"qualname": 2, "fullname": 5, "annotation": 7, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "ffmpeg_bitrate_stats.BitrateStats.bitrate_stats": {"qualname": 3, "fullname": 6, "annotation": 9, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "ffmpeg_bitrate_stats.BitrateStats.rounding_factor": {"qualname": 3, "fullname": 6, "annotation": 2, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "ffmpeg_bitrate_stats.BitrateStats.calculate_statistics": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 27, "bases": 0, "doc": 39}, "ffmpeg_bitrate_stats.BitrateStats.print_statistics": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 45, "bases": 0, "doc": 53}, "ffmpeg_bitrate_stats.BitrateStats.get_csv": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 14, "bases": 0, "doc": 46}, "ffmpeg_bitrate_stats.BitrateStats.get_json": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 14, "bases": 0, "doc": 46}, "ffmpeg_bitrate_stats.BitrateStats.plot": {"qualname": 2, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 48, "bases": 0, "doc": 49}, "ffmpeg_bitrate_stats.BitrateStatsSummary": {"qualname": 1, "fullname": 4, "annotation": 0, "default_value": 0, "signature": 0, "bases": 2, "doc": 3}, "ffmpeg_bitrate_stats.BitrateStatsSummary.input_file": {"qualname": 3, "fullname": 6, "annotation": 2, "default_value": 0, "signature": 0, "bases": 0, "doc": 6}, "ffmpeg_bitrate_stats.BitrateStatsSummary.stream_type": {"qualname": 3, "fullname": 6, "annotation": 9, "default_value": 0, "signature": 0, "bases": 0, "doc": 7}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_fps": {"qualname": 3, "fullname": 6, "annotation": 2, "default_value": 0, "signature": 0, "bases": 0, "doc": 6}, "ffmpeg_bitrate_stats.BitrateStatsSummary.num_frames": {"qualname": 3, "fullname": 6, "annotation": 2, "default_value": 0, "signature": 0, "bases": 0, "doc": 7}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate": {"qualname": 3, "fullname": 6, "annotation": 2, "default_value": 0, "signature": 0, "bases": 0, "doc": 8}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate_over_chunks": {"qualname": 5, "fullname": 8, "annotation": 2, "default_value": 0, "signature": 0, "bases": 0, "doc": 10}, "ffmpeg_bitrate_stats.BitrateStatsSummary.max_bitrate": {"qualname": 3, "fullname": 6, "annotation": 2, "default_value": 0, "signature": 0, "bases": 0, "doc": 8}, "ffmpeg_bitrate_stats.BitrateStatsSummary.min_bitrate": {"qualname": 3, "fullname": 6, "annotation": 2, "default_value": 0, "signature": 0, "bases": 0, "doc": 8}, "ffmpeg_bitrate_stats.BitrateStatsSummary.max_bitrate_factor": {"qualname": 4, "fullname": 7, "annotation": 2, "default_value": 0, "signature": 0, "bases": 0, "doc": 8}, "ffmpeg_bitrate_stats.BitrateStatsSummary.bitrate_per_chunk": {"qualname": 4, "fullname": 7, "annotation": 2, "default_value": 0, "signature": 0, "bases": 0, "doc": 9}, "ffmpeg_bitrate_stats.BitrateStatsSummary.aggregation": {"qualname": 2, "fullname": 5, "annotation": 9, "default_value": 0, "signature": 0, "bases": 0, "doc": 7}, "ffmpeg_bitrate_stats.BitrateStatsSummary.chunk_size": {"qualname": 3, "fullname": 6, "annotation": 2, "default_value": 0, "signature": 0, "bases": 0, "doc": 8}, "ffmpeg_bitrate_stats.BitrateStatsSummary.duration": {"qualname": 2, "fullname": 5, "annotation": 2, "default_value": 0, "signature": 0, "bases": 0, "doc": 7}, "ffmpeg_bitrate_stats.run_command": {"qualname": 2, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 75, "bases": 0, "doc": 6}}, "length": 37, "save": true}, "index": {"qualname": {"root": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.__init__": {"tf": 1}}, "df": 1, "b": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.max_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.min_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.moving_avg_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.bitrate_stats": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate_over_chunks": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.max_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.min_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.max_bitrate_factor": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.bitrate_per_chunk": {"tf": 1}}, "df": 10, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "s": {"docs": {"ffmpeg_bitrate_stats.BitrateStats": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.__init__": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.input_file": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.stream_type": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.aggregation": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.chunk_size": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.read_length": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.dry_run": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.duration": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.fps": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.max_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.min_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.moving_avg_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.frames": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.bitrate_stats": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.rounding_factor": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.calculate_statistics": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.print_statistics": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.get_csv": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.get_json": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.plot": {"tf": 1}}, "df": 21, "s": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "y": {"docs": {"ffmpeg_bitrate_stats.BitrateStatsSummary": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.input_file": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.stream_type": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_fps": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.num_frames": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate_over_chunks": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.max_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.min_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.max_bitrate_factor": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.bitrate_per_chunk": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.aggregation": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.chunk_size": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.duration": {"tf": 1}}, "df": 14}}}}}}}}}}}}}}}}}}}, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.__init__": {"tf": 1}}, "df": 1}}, "p": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "t": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.input_file": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.input_file": {"tf": 1}}, "df": 2}}}}}, "f": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.input_file": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.input_file": {"tf": 1}}, "df": 2}}}, "p": {"docs": {}, "df": 0, "s": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.fps": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_fps": {"tf": 1}}, "df": 2}}, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.frames": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.num_frames": {"tf": 1}}, "df": 2}}}}}, "a": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.rounding_factor": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.max_bitrate_factor": {"tf": 1}}, "df": 2}}}}}}, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.stream_type": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.stream_type": {"tf": 1}}, "df": 2}}}}, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "s": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.bitrate_stats": {"tf": 1}}, "df": 1}, "i": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "s": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.calculate_statistics": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.print_statistics": {"tf": 1}}, "df": 2}}}}}}}}}, "i": {"docs": {}, "df": 0, "z": {"docs": {}, "df": 0, "e": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.chunk_size": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.chunk_size": {"tf": 1}}, "df": 2}}}}, "t": {"docs": {}, "df": 0, "y": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.stream_type": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.stream_type": {"tf": 1}}, "df": 2}}}}, "a": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.aggregation": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.aggregation": {"tf": 1}}, "df": 2}}}}}}}}}}, "v": {"docs": {}, "df": 0, "g": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.moving_avg_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_fps": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate_over_chunks": {"tf": 1}}, "df": 4}}}, "c": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "k": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.chunk_size": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.bitrate_per_chunk": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.chunk_size": {"tf": 1}}, "df": 3, "s": {"docs": {"ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate_over_chunks": {"tf": 1}}, "df": 1}}}}}, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.calculate_statistics": {"tf": 1}}, "df": 1}}}}}}}}, "s": {"docs": {}, "df": 0, "v": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.get_csv": {"tf": 1}}, "df": 1}}, "o": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "d": {"docs": {"ffmpeg_bitrate_stats.run_command": {"tf": 1}}, "df": 1}}}}}}}, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "d": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.read_length": {"tf": 1}}, "df": 1}}}, "u": {"docs": {}, "df": 0, "n": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.dry_run": {"tf": 1}, "ffmpeg_bitrate_stats.run_command": {"tf": 1}}, "df": 2}}, "o": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.rounding_factor": {"tf": 1}}, "df": 1}}}}}}}}, "l": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.read_length": {"tf": 1}}, "df": 1}}}}}}, "d": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "y": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.dry_run": {"tf": 1}}, "df": 1}}, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.duration": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.duration": {"tf": 1}}, "df": 2}}}}}}}}, "m": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "x": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.max_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.max_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.max_bitrate_factor": {"tf": 1}}, "df": 3}}, "i": {"docs": {}, "df": 0, "n": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.min_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.min_bitrate": {"tf": 1}}, "df": 2}}, "o": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.moving_avg_bitrate": {"tf": 1}}, "df": 1}}}}}}, "p": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.print_statistics": {"tf": 1}}, "df": 1}}}}, "l": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "t": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.plot": {"tf": 1}}, "df": 1}}}, "e": {"docs": {}, "df": 0, "r": {"docs": {"ffmpeg_bitrate_stats.BitrateStatsSummary.bitrate_per_chunk": {"tf": 1}}, "df": 1}}}, "g": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.get_csv": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.get_json": {"tf": 1}}, "df": 2}}}, "j": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.get_json": {"tf": 1}}, "df": 1}}}}, "n": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "m": {"docs": {"ffmpeg_bitrate_stats.BitrateStatsSummary.num_frames": {"tf": 1}}, "df": 1}}}, "o": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate_over_chunks": {"tf": 1}}, "df": 1}}}}}}, "fullname": {"root": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.__init__": {"tf": 1}}, "df": 1, "f": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "g": {"docs": {"ffmpeg_bitrate_stats": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.__init__": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.input_file": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.stream_type": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.aggregation": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.chunk_size": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.read_length": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.dry_run": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.duration": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.fps": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.max_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.min_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.moving_avg_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.frames": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.bitrate_stats": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.rounding_factor": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.calculate_statistics": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.print_statistics": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.get_csv": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.get_json": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.plot": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.input_file": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.stream_type": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_fps": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.num_frames": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate_over_chunks": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.max_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.min_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.max_bitrate_factor": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.bitrate_per_chunk": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.aggregation": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.chunk_size": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.duration": {"tf": 1}, "ffmpeg_bitrate_stats.run_command": {"tf": 1}}, "df": 37}}}}}, "i": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.input_file": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.input_file": {"tf": 1}}, "df": 2}}}, "p": {"docs": {}, "df": 0, "s": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.fps": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_fps": {"tf": 1}}, "df": 2}}, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.frames": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.num_frames": {"tf": 1}}, "df": 2}}}}}, "a": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.rounding_factor": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.max_bitrate_factor": {"tf": 1}}, "df": 2}}}}}}, "b": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"ffmpeg_bitrate_stats": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.__init__": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.input_file": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.stream_type": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.aggregation": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.chunk_size": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.read_length": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.dry_run": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.duration": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.fps": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.max_bitrate": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStats.min_bitrate": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStats.moving_avg_bitrate": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStats.frames": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.bitrate_stats": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStats.rounding_factor": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.calculate_statistics": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.print_statistics": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.get_csv": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.get_json": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.plot": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.input_file": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.stream_type": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_fps": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.num_frames": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate_over_chunks": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStatsSummary.max_bitrate": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStatsSummary.min_bitrate": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStatsSummary.max_bitrate_factor": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStatsSummary.bitrate_per_chunk": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStatsSummary.aggregation": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.chunk_size": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.duration": {"tf": 1}, "ffmpeg_bitrate_stats.run_command": {"tf": 1}}, "df": 37, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "s": {"docs": {"ffmpeg_bitrate_stats.BitrateStats": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.__init__": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.input_file": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.stream_type": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.aggregation": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.chunk_size": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.read_length": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.dry_run": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.duration": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.fps": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.max_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.min_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.moving_avg_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.frames": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.bitrate_stats": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.rounding_factor": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.calculate_statistics": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.print_statistics": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.get_csv": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.get_json": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.plot": {"tf": 1}}, "df": 21, "s": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "y": {"docs": {"ffmpeg_bitrate_stats.BitrateStatsSummary": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.input_file": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.stream_type": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_fps": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.num_frames": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate_over_chunks": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.max_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.min_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.max_bitrate_factor": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.bitrate_per_chunk": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.aggregation": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.chunk_size": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.duration": {"tf": 1}}, "df": 14}}}}}}}}}}}}}}}}}}}, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "s": {"docs": {"ffmpeg_bitrate_stats": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.__init__": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.input_file": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.stream_type": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.aggregation": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.chunk_size": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.read_length": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.dry_run": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.duration": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.fps": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.max_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.min_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.moving_avg_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.frames": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.bitrate_stats": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStats.rounding_factor": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.calculate_statistics": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.print_statistics": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.get_csv": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.get_json": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.plot": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.input_file": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.stream_type": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_fps": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.num_frames": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate_over_chunks": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.max_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.min_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.max_bitrate_factor": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.bitrate_per_chunk": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.aggregation": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.chunk_size": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.duration": {"tf": 1}, "ffmpeg_bitrate_stats.run_command": {"tf": 1}}, "df": 37}, "i": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "s": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.calculate_statistics": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.print_statistics": {"tf": 1}}, "df": 2}}}}}}}}, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.stream_type": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.stream_type": {"tf": 1}}, "df": 2}}}}}, "i": {"docs": {}, "df": 0, "z": {"docs": {}, "df": 0, "e": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.chunk_size": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.chunk_size": {"tf": 1}}, "df": 2}}}}, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.__init__": {"tf": 1}}, "df": 1}}, "p": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "t": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.input_file": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.input_file": {"tf": 1}}, "df": 2}}}}}, "t": {"docs": {}, "df": 0, "y": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.stream_type": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.stream_type": {"tf": 1}}, "df": 2}}}}, "a": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.aggregation": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.aggregation": {"tf": 1}}, "df": 2}}}}}}}}}}, "v": {"docs": {}, "df": 0, "g": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.moving_avg_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_fps": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate_over_chunks": {"tf": 1}}, "df": 4}}}, "c": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "k": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.chunk_size": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.bitrate_per_chunk": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.chunk_size": {"tf": 1}}, "df": 3, "s": {"docs": {"ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate_over_chunks": {"tf": 1}}, "df": 1}}}}}, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.calculate_statistics": {"tf": 1}}, "df": 1}}}}}}}}, "s": {"docs": {}, "df": 0, "v": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.get_csv": {"tf": 1}}, "df": 1}}, "o": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "d": {"docs": {"ffmpeg_bitrate_stats.run_command": {"tf": 1}}, "df": 1}}}}}}}, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "d": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.read_length": {"tf": 1}}, "df": 1}}}, "u": {"docs": {}, "df": 0, "n": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.dry_run": {"tf": 1}, "ffmpeg_bitrate_stats.run_command": {"tf": 1}}, "df": 2}}, "o": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.rounding_factor": {"tf": 1}}, "df": 1}}}}}}}}, "l": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.read_length": {"tf": 1}}, "df": 1}}}}}}, "d": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "y": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.dry_run": {"tf": 1}}, "df": 1}}, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.duration": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.duration": {"tf": 1}}, "df": 2}}}}}}}}, "m": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "x": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.max_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.max_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.max_bitrate_factor": {"tf": 1}}, "df": 3}}, "i": {"docs": {}, "df": 0, "n": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.min_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.min_bitrate": {"tf": 1}}, "df": 2}}, "o": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.moving_avg_bitrate": {"tf": 1}}, "df": 1}}}}}}, "p": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.print_statistics": {"tf": 1}}, "df": 1}}}}, "l": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "t": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.plot": {"tf": 1}}, "df": 1}}}, "e": {"docs": {}, "df": 0, "r": {"docs": {"ffmpeg_bitrate_stats.BitrateStatsSummary.bitrate_per_chunk": {"tf": 1}}, "df": 1}}}, "g": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.get_csv": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.get_json": {"tf": 1}}, "df": 2}}}, "j": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.get_json": {"tf": 1}}, "df": 1}}}}, "n": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "m": {"docs": {"ffmpeg_bitrate_stats.BitrateStatsSummary.num_frames": {"tf": 1}}, "df": 1}}}, "o": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate_over_chunks": {"tf": 1}}, "df": 1}}}}}}, "annotation": {"root": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.stream_type": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStats.aggregation": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStats.read_length": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.duration": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.fps": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.max_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.min_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.moving_avg_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.frames": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.bitrate_stats": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStats.rounding_factor": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.input_file": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.stream_type": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_fps": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.num_frames": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate_over_chunks": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.max_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.min_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.max_bitrate_factor": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.bitrate_per_chunk": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.aggregation": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStatsSummary.chunk_size": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.duration": {"tf": 1}}, "df": 24, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.stream_type": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.aggregation": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.stream_type": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.aggregation": {"tf": 1}}, "df": 4}}}}}, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "[": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.moving_avg_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.bitrate_per_chunk": {"tf": 1}}, "df": 2}}}}, "f": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "g": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.frames": {"tf": 1}}, "df": 1}}}}}}}}}}}, "x": {"2": {"7": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.stream_type": {"tf": 2}, "ffmpeg_bitrate_stats.BitrateStats.aggregation": {"tf": 2}, "ffmpeg_bitrate_stats.BitrateStatsSummary.stream_type": {"tf": 2}, "ffmpeg_bitrate_stats.BitrateStatsSummary.aggregation": {"tf": 2}}, "df": 4}, "docs": {}, "df": 0}, "docs": {}, "df": 0}, "a": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.stream_type": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.stream_type": {"tf": 1}}, "df": 2}}}}}, "v": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "o": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.stream_type": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.stream_type": {"tf": 1}}, "df": 2}}}}}, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.aggregation": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.aggregation": {"tf": 1}}, "df": 2}}}}, "g": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "p": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.aggregation": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.aggregation": {"tf": 1}}, "df": 2}}}, "o": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "[": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "r": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.read_length": {"tf": 1}}, "df": 1}}}, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {"ffmpeg_bitrate_stats.BitrateStatsSummary.chunk_size": {"tf": 1}}, "df": 1}}}}}}}}}}}}, "f": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.duration": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.fps": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.max_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.min_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_fps": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate_over_chunks": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.max_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.min_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.max_bitrate_factor": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.duration": {"tf": 1}}, "df": 11}}}}, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "y": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.frames": {"tf": 1}}, "df": 1}}}}}}}}}, "f": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "g": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.bitrate_stats": {"tf": 1}}, "df": 1}}}}}}, "b": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.frames": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStats.bitrate_stats": {"tf": 1.4142135623730951}}, "df": 2, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "y": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.bitrate_stats": {"tf": 1}}, "df": 1}}}}}}}}}}}}}}}}}}}, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "s": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.frames": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStats.bitrate_stats": {"tf": 1.4142135623730951}}, "df": 2}}}, "r": {"docs": {"ffmpeg_bitrate_stats.BitrateStatsSummary.input_file": {"tf": 1}}, "df": 1}}}, "n": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.bitrate_stats": {"tf": 1}}, "df": 1}}}}, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.rounding_factor": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.num_frames": {"tf": 1}}, "df": 2}}}}}, "default_value": {"root": {"docs": {}, "df": 0}}, "signature": {"root": {"1": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.__init__": {"tf": 1}}, "df": 1}, "3": {"0": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.plot": {"tf": 1}}, "df": 1}, "9": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.__init__": {"tf": 3.4641016151377544}, "ffmpeg_bitrate_stats.BitrateStats.print_statistics": {"tf": 2}}, "df": 2}, "docs": {}, "df": 0}, "8": {"0": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.plot": {"tf": 1}}, "df": 1}, "docs": {}, "df": 0}, "docs": {"ffmpeg_bitrate_stats.BitrateStats.__init__": {"tf": 12.041594578792296}, "ffmpeg_bitrate_stats.BitrateStats.calculate_statistics": {"tf": 4.47213595499958}, "ffmpeg_bitrate_stats.BitrateStats.print_statistics": {"tf": 5.830951894845301}, "ffmpeg_bitrate_stats.BitrateStats.get_csv": {"tf": 3.4641016151377544}, "ffmpeg_bitrate_stats.BitrateStats.get_json": {"tf": 3.4641016151377544}, "ffmpeg_bitrate_stats.BitrateStats.plot": {"tf": 6.324555320336759}, "ffmpeg_bitrate_stats.run_command": {"tf": 7.874007874011811}}, "df": 7, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "t": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.__init__": {"tf": 1}}, "df": 1}}}, "t": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.__init__": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.plot": {"tf": 1.4142135623730951}}, "df": 2}}}, "f": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.__init__": {"tf": 1}}, "df": 1}}}, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.__init__": {"tf": 1}, "ffmpeg_bitrate_stats.run_command": {"tf": 1}}, "df": 2}}}}, "f": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "g": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.calculate_statistics": {"tf": 1}}, "df": 1}}}}}, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.print_statistics": {"tf": 1}}, "df": 1}}}}}}, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "r": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.__init__": {"tf": 1.7320508075688772}, "ffmpeg_bitrate_stats.BitrateStats.get_csv": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.get_json": {"tf": 1}, "ffmpeg_bitrate_stats.run_command": {"tf": 1.7320508075688772}}, "df": 4, "e": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.__init__": {"tf": 1}}, "df": 1}}}}, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "t": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.__init__": {"tf": 1}}, "df": 1}}, "t": {"docs": {}, "df": 0, "s": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.calculate_statistics": {"tf": 1.4142135623730951}}, "df": 1}}}}, "i": {"docs": {}, "df": 0, "z": {"docs": {}, "df": 0, "e": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.__init__": {"tf": 1}}, "df": 1}}}, "e": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "f": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.calculate_statistics": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.print_statistics": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.get_csv": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.get_json": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.plot": {"tf": 1}}, "df": 5}}}}, "t": {"docs": {}, "df": 0, "y": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.__init__": {"tf": 1}}, "df": 1}}}, "i": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.__init__": {"tf": 1.4142135623730951}}, "df": 1}}}, "u": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"ffmpeg_bitrate_stats.run_command": {"tf": 1.4142135623730951}}, "df": 1}}}}}, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.__init__": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStats.print_statistics": {"tf": 1}}, "df": 2}}}}}, "s": {"docs": {}, "df": 0, "t": {"docs": {"ffmpeg_bitrate_stats.run_command": {"tf": 1}}, "df": 1}}}}, "a": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.__init__": {"tf": 1}}, "df": 1}}}}, "g": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.__init__": {"tf": 1}}, "df": 1}}}}}}}}}}}, "v": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "o": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.__init__": {"tf": 1.4142135623730951}}, "df": 1}}}}}, "g": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "p": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.__init__": {"tf": 1}}, "df": 1}}}, "c": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "k": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.__init__": {"tf": 1}}, "df": 1}}}}, "s": {"docs": {}, "df": 0, "v": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.print_statistics": {"tf": 1}}, "df": 1}}, "m": {"docs": {}, "df": 0, "d": {"docs": {"ffmpeg_bitrate_stats.run_command": {"tf": 1}}, "df": 1}}}, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "d": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.__init__": {"tf": 1.4142135623730951}}, "df": 1}}}, "u": {"docs": {}, "df": 0, "n": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.__init__": {"tf": 1}, "ffmpeg_bitrate_stats.run_command": {"tf": 1}}, "df": 2}}}, "o": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.__init__": {"tf": 1.4142135623730951}}, "df": 1}}}}}}}, "u": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "t": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.print_statistics": {"tf": 1}}, "df": 1}}}}}}, "n": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.__init__": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStats.print_statistics": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.plot": {"tf": 1}, "ffmpeg_bitrate_stats.run_command": {"tf": 1.4142135623730951}}, "df": 4}}}}, "d": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.__init__": {"tf": 1}}, "df": 1}}}}}}}, "r": {"docs": {}, "df": 0, "y": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.__init__": {"tf": 1}, "ffmpeg_bitrate_stats.run_command": {"tf": 1}}, "df": 2}}}, "b": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "l": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.__init__": {"tf": 1}, "ffmpeg_bitrate_stats.run_command": {"tf": 1}}, "df": 2}}}, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.calculate_statistics": {"tf": 1.4142135623730951}}, "df": 1, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "y": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.calculate_statistics": {"tf": 1}}, "df": 1}}}}}}}}}}}}}}}}}}}, "j": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.print_statistics": {"tf": 1}}, "df": 1}}}}, "w": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.plot": {"tf": 1}}, "df": 1}}}}}, "h": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "t": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.plot": {"tf": 1}}, "df": 1}}}}}}}}, "bases": {"root": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "y": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"ffmpeg_bitrate_stats.BitrateStatsSummary": {"tf": 1}}, "df": 1}}}, "e": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {"ffmpeg_bitrate_stats.BitrateStatsSummary": {"tf": 1}}, "df": 1}}}}}}}}}}}, "doc": {"root": {"1": {"docs": {"ffmpeg_bitrate_stats.BitrateStats": {"tf": 1}}, "df": 1}, "3": {"0": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.plot": {"tf": 1}}, "df": 1}, "docs": {}, "df": 0}, "8": {"0": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.plot": {"tf": 1}}, "df": 1}, "docs": {}, "df": 0}, "docs": {"ffmpeg_bitrate_stats": {"tf": 1.7320508075688772}, "ffmpeg_bitrate_stats.BitrateStats": {"tf": 7.0710678118654755}, "ffmpeg_bitrate_stats.BitrateStats.__init__": {"tf": 1.7320508075688772}, "ffmpeg_bitrate_stats.BitrateStats.input_file": {"tf": 1.7320508075688772}, "ffmpeg_bitrate_stats.BitrateStats.stream_type": {"tf": 1.7320508075688772}, "ffmpeg_bitrate_stats.BitrateStats.aggregation": {"tf": 1.7320508075688772}, "ffmpeg_bitrate_stats.BitrateStats.chunk_size": {"tf": 1.7320508075688772}, "ffmpeg_bitrate_stats.BitrateStats.read_length": {"tf": 1.7320508075688772}, "ffmpeg_bitrate_stats.BitrateStats.dry_run": {"tf": 1.7320508075688772}, "ffmpeg_bitrate_stats.BitrateStats.duration": {"tf": 1.7320508075688772}, "ffmpeg_bitrate_stats.BitrateStats.fps": {"tf": 1.7320508075688772}, "ffmpeg_bitrate_stats.BitrateStats.max_bitrate": {"tf": 1.7320508075688772}, "ffmpeg_bitrate_stats.BitrateStats.min_bitrate": {"tf": 1.7320508075688772}, "ffmpeg_bitrate_stats.BitrateStats.moving_avg_bitrate": {"tf": 1.7320508075688772}, "ffmpeg_bitrate_stats.BitrateStats.frames": {"tf": 1.7320508075688772}, "ffmpeg_bitrate_stats.BitrateStats.bitrate_stats": {"tf": 1.7320508075688772}, "ffmpeg_bitrate_stats.BitrateStats.rounding_factor": {"tf": 1.7320508075688772}, "ffmpeg_bitrate_stats.BitrateStats.calculate_statistics": {"tf": 4.795831523312719}, "ffmpeg_bitrate_stats.BitrateStats.print_statistics": {"tf": 4.898979485566356}, "ffmpeg_bitrate_stats.BitrateStats.get_csv": {"tf": 4.58257569495584}, "ffmpeg_bitrate_stats.BitrateStats.get_json": {"tf": 4.58257569495584}, "ffmpeg_bitrate_stats.BitrateStats.plot": {"tf": 4.58257569495584}, "ffmpeg_bitrate_stats.BitrateStatsSummary": {"tf": 1.7320508075688772}, "ffmpeg_bitrate_stats.BitrateStatsSummary.input_file": {"tf": 1.7320508075688772}, "ffmpeg_bitrate_stats.BitrateStatsSummary.stream_type": {"tf": 1.7320508075688772}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_fps": {"tf": 1.7320508075688772}, "ffmpeg_bitrate_stats.BitrateStatsSummary.num_frames": {"tf": 1.7320508075688772}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate": {"tf": 1.7320508075688772}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate_over_chunks": {"tf": 1.7320508075688772}, "ffmpeg_bitrate_stats.BitrateStatsSummary.max_bitrate": {"tf": 1.7320508075688772}, "ffmpeg_bitrate_stats.BitrateStatsSummary.min_bitrate": {"tf": 1.7320508075688772}, "ffmpeg_bitrate_stats.BitrateStatsSummary.max_bitrate_factor": {"tf": 1.7320508075688772}, "ffmpeg_bitrate_stats.BitrateStatsSummary.bitrate_per_chunk": {"tf": 1.7320508075688772}, "ffmpeg_bitrate_stats.BitrateStatsSummary.aggregation": {"tf": 1.7320508075688772}, "ffmpeg_bitrate_stats.BitrateStatsSummary.chunk_size": {"tf": 1.7320508075688772}, "ffmpeg_bitrate_stats.BitrateStatsSummary.duration": {"tf": 1.7320508075688772}, "ffmpeg_bitrate_stats.run_command": {"tf": 1.4142135623730951}}, "df": 37, "i": {"docs": {}, "df": 0, "n": {"docs": {"ffmpeg_bitrate_stats.BitrateStats": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStats.print_statistics": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate_over_chunks": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.max_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.min_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.bitrate_per_chunk": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.chunk_size": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.duration": {"tf": 1}}, "df": 9, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "z": {"docs": {}, "df": 0, "e": {"docs": {"ffmpeg_bitrate_stats.BitrateStats": {"tf": 1}}, "df": 1}}}}}}}}, "p": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "t": {"docs": {"ffmpeg_bitrate_stats.BitrateStats": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStatsSummary.input_file": {"tf": 1}}, "df": 2}}}, "t": {"docs": {"ffmpeg_bitrate_stats.BitrateStats": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.plot": {"tf": 1.4142135623730951}}, "df": 2}, "v": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "d": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.print_statistics": {"tf": 1}}, "df": 1}}}}}}, "f": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.calculate_statistics": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.print_statistics": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.get_csv": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.get_json": {"tf": 1}}, "df": 4}, "s": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.print_statistics": {"tf": 1}}, "df": 1}}, "t": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "e": {"docs": {"ffmpeg_bitrate_stats.BitrateStats": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStats.calculate_statistics": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStats.print_statistics": {"tf": 2.23606797749979}, "ffmpeg_bitrate_stats.BitrateStats.get_csv": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStats.get_json": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStats.plot": {"tf": 1.7320508075688772}, "ffmpeg_bitrate_stats.BitrateStatsSummary.input_file": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.stream_type": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_fps": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.num_frames": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate_over_chunks": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.max_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.min_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.bitrate_per_chunk": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.aggregation": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.chunk_size": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.duration": {"tf": 1}}, "df": 18}}, "o": {"docs": {"ffmpeg_bitrate_stats.BitrateStats": {"tf": 2.6457513110645907}, "ffmpeg_bitrate_stats.BitrateStats.print_statistics": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStats.plot": {"tf": 1.7320508075688772}}, "df": 3}, "y": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {"ffmpeg_bitrate_stats.BitrateStats": {"tf": 1.7320508075688772}, "ffmpeg_bitrate_stats.BitrateStatsSummary.stream_type": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.aggregation": {"tf": 1}}, "df": 3}}}, "i": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {"ffmpeg_bitrate_stats.BitrateStats": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStats.plot": {"tf": 1}}, "df": 2, "/": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "p": {"docs": {"ffmpeg_bitrate_stats.BitrateStats": {"tf": 1}}, "df": 1}}}, "c": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "k": {"docs": {}, "df": 0, "s": {"docs": {"ffmpeg_bitrate_stats.BitrateStatsSummary.aggregation": {"tf": 1}}, "df": 1}}}}}}}}}}}, "b": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.calculate_statistics": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStats.get_csv": {"tf": 1.7320508075688772}, "ffmpeg_bitrate_stats.BitrateStats.get_json": {"tf": 1.7320508075688772}, "ffmpeg_bitrate_stats.BitrateStats.plot": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate_over_chunks": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.max_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.min_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.bitrate_per_chunk": {"tf": 1}}, "df": 9, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "s": {"docs": {"ffmpeg_bitrate_stats.BitrateStats": {"tf": 1}}, "df": 1}}}}}}}}}}}, "o": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "l": {"docs": {"ffmpeg_bitrate_stats.BitrateStats": {"tf": 1}}, "df": 1}}}, "e": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "w": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {"ffmpeg_bitrate_stats.BitrateStatsSummary.max_bitrate_factor": {"tf": 1}}, "df": 1}}}}}}}, "c": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {"ffmpeg_bitrate_stats.BitrateStats": {"tf": 1}}, "df": 1}}}}, "h": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "k": {"docs": {"ffmpeg_bitrate_stats.BitrateStats": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStatsSummary.bitrate_per_chunk": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.chunk_size": {"tf": 1}}, "df": 3, "s": {"docs": {"ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate_over_chunks": {"tf": 1}}, "df": 1}}}}}, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.calculate_statistics": {"tf": 1}}, "df": 1}}}}}}}}, "s": {"docs": {}, "df": 0, "v": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.print_statistics": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.get_csv": {"tf": 1.4142135623730951}}, "df": 2}}, "o": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "d": {"docs": {"ffmpeg_bitrate_stats.run_command": {"tf": 1}}, "df": 1}}}}}}}, "a": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.get_csv": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStats.get_json": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.run_command": {"tf": 1}}, "df": 3, "r": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "s": {"docs": {"ffmpeg_bitrate_stats.BitrateStats": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.print_statistics": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.plot": {"tf": 1}}, "df": 3}}}}}}}, "e": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.get_csv": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.get_json": {"tf": 1}}, "df": 2}}, "u": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "/": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "o": {"docs": {"ffmpeg_bitrate_stats.BitrateStats": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.stream_type": {"tf": 1}}, "df": 2}}}}}}}}}}, "g": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"ffmpeg_bitrate_stats.BitrateStats": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStatsSummary.aggregation": {"tf": 1}}, "df": 2}}}}}}}}}}, "n": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.calculate_statistics": {"tf": 1}}, "df": 1, "d": {"docs": {"ffmpeg_bitrate_stats.BitrateStatsSummary.max_bitrate_factor": {"tf": 1}}, "df": 1}}, "s": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.get_csv": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStats.get_json": {"tf": 1.4142135623730951}}, "df": 2}, "v": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.get_csv": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.get_json": {"tf": 1}}, "df": 2}}}}}}}, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "e": {"docs": {"ffmpeg_bitrate_stats.BitrateStatsSummary.avg_fps": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate_over_chunks": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.max_bitrate_factor": {"tf": 1}}, "df": 4}}}}}}}, "f": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"ffmpeg_bitrate_stats.BitrateStats": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStatsSummary.input_file": {"tf": 1}}, "df": 2}}}, "o": {"docs": {}, "df": 0, "r": {"docs": {"ffmpeg_bitrate_stats.BitrateStats": {"tf": 1.4142135623730951}}, "df": 1, "m": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.print_statistics": {"tf": 2}}, "df": 1}}}}}, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {"ffmpeg_bitrate_stats.BitrateStats": {"tf": 1}}, "df": 1}}}}, "p": {"docs": {}, "df": 0, "s": {"docs": {"ffmpeg_bitrate_stats.BitrateStatsSummary.avg_fps": {"tf": 1}}, "df": 1}}, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"ffmpeg_bitrate_stats.BitrateStatsSummary.num_frames": {"tf": 1}}, "df": 1}}}}}}, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "r": {"docs": {"ffmpeg_bitrate_stats.BitrateStats": {"tf": 2.23606797749979}, "ffmpeg_bitrate_stats.BitrateStats.get_csv": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.get_json": {"tf": 1}}, "df": 3, "e": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {"ffmpeg_bitrate_stats.BitrateStats": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStatsSummary.stream_type": {"tf": 1}}, "df": 2}}}, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.get_csv": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStats.get_json": {"tf": 1.4142135623730951}}, "df": 2}}}}, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "t": {"docs": {"ffmpeg_bitrate_stats.BitrateStats": {"tf": 1.4142135623730951}}, "df": 1}}, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "s": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.calculate_statistics": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStats.print_statistics": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStats.get_csv": {"tf": 1.7320508075688772}, "ffmpeg_bitrate_stats.BitrateStats.get_json": {"tf": 1.7320508075688772}}, "df": 4}}}}}}}}, "d": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "t": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.print_statistics": {"tf": 1}}, "df": 1}}}, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "r": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.plot": {"tf": 1}}, "df": 1}}}}}, "i": {"docs": {}, "df": 0, "z": {"docs": {}, "df": 0, "e": {"docs": {"ffmpeg_bitrate_stats.BitrateStats": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStatsSummary.chunk_size": {"tf": 1}}, "df": 2}}}, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "s": {"docs": {"ffmpeg_bitrate_stats.BitrateStats": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStatsSummary.chunk_size": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.duration": {"tf": 1}}, "df": 3}}}}}}, "u": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "y": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.calculate_statistics": {"tf": 1}}, "df": 1}}}}}}, "p": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.print_statistics": {"tf": 1}}, "df": 1}}}}}}}}}, "p": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {"ffmpeg_bitrate_stats.BitrateStats": {"tf": 1}}, "df": 1}}}, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.print_statistics": {"tf": 1.4142135623730951}}, "df": 1}}}}, "l": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "t": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.plot": {"tf": 1.7320508075688772}}, "df": 1}}}, "e": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "k": {"docs": {"ffmpeg_bitrate_stats.BitrateStatsSummary.max_bitrate_factor": {"tf": 1}}, "df": 1}}, "r": {"docs": {"ffmpeg_bitrate_stats.BitrateStatsSummary.bitrate_per_chunk": {"tf": 1}}, "df": 1}}}, "o": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {"ffmpeg_bitrate_stats.BitrateStats": {"tf": 2.449489742783178}, "ffmpeg_bitrate_stats.BitrateStats.plot": {"tf": 1.4142135623730951}}, "df": 2}}}}}}}, "r": {"docs": {"ffmpeg_bitrate_stats.BitrateStats": {"tf": 1.4142135623730951}}, "df": 1}, "c": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.calculate_statistics": {"tf": 1}}, "df": 1}}}}}}}, "u": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "t": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.print_statistics": {"tf": 1.4142135623730951}}, "df": 1}}}}}, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.plot": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate_over_chunks": {"tf": 1}}, "df": 2}}}, "f": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.plot": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStatsSummary.num_frames": {"tf": 1}}, "df": 2}}, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "s": {"docs": {"ffmpeg_bitrate_stats.BitrateStats": {"tf": 2.449489742783178}, "ffmpeg_bitrate_stats.BitrateStats.plot": {"tf": 1.4142135623730951}}, "df": 2}}}}}}}, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"ffmpeg_bitrate_stats.BitrateStats": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.BitrateStatsSummary.duration": {"tf": 1}}, "df": 2}}}}}}}, "r": {"docs": {}, "df": 0, "y": {"docs": {"ffmpeg_bitrate_stats.BitrateStats": {"tf": 1.4142135623730951}}, "df": 1}}, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.calculate_statistics": {"tf": 1}}, "df": 1}}, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "y": {"docs": {"ffmpeg_bitrate_stats.run_command": {"tf": 1}}, "df": 1}}}}}}}}, "v": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "o": {"docs": {"ffmpeg_bitrate_stats.BitrateStats": {"tf": 1}}, "df": 1}}}}, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.print_statistics": {"tf": 1}}, "df": 1}}}}}}}}}}, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "d": {"docs": {"ffmpeg_bitrate_stats.BitrateStats": {"tf": 1.4142135623730951}}, "df": 1, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"ffmpeg_bitrate_stats.BitrateStats": {"tf": 1.4142135623730951}}, "df": 1}}}}}, "t": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "s": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.calculate_statistics": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.get_csv": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.get_json": {"tf": 1}}, "df": 3}}}}}, "l": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"ffmpeg_bitrate_stats.BitrateStatsSummary.max_bitrate_factor": {"tf": 1}}, "df": 1}}}}}}}, "u": {"docs": {}, "df": 0, "n": {"docs": {"ffmpeg_bitrate_stats.BitrateStats": {"tf": 1.4142135623730951}, "ffmpeg_bitrate_stats.run_command": {"tf": 1}}, "df": 2, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.calculate_statistics": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.get_csv": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.get_json": {"tf": 1}}, "df": 3}}}}}}}}}}}, "a": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.calculate_statistics": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.print_statistics": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.get_csv": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.get_json": {"tf": 1}}, "df": 4}}}}}}, "h": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, ":": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, ":": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {"ffmpeg_bitrate_stats.BitrateStats": {"tf": 1.4142135623730951}}, "df": 1}}}}}}}, "e": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "t": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.plot": {"tf": 1.4142135623730951}}, "df": 1}}}}}}, "m": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {"ffmpeg_bitrate_stats.BitrateStats": {"tf": 1.4142135623730951}}, "df": 1}}}, "a": {"docs": {}, "df": 0, "x": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "m": {"docs": {"ffmpeg_bitrate_stats.BitrateStatsSummary.max_bitrate": {"tf": 1}}, "df": 1}}}}}}, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "m": {"docs": {"ffmpeg_bitrate_stats.BitrateStatsSummary.min_bitrate": {"tf": 1}}, "df": 1}}}}}}}, "n": {"docs": {}, "df": 0, "o": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.get_csv": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.get_json": {"tf": 1}}, "df": 2, "n": {"docs": {}, "df": 0, "e": {"docs": {"ffmpeg_bitrate_stats.BitrateStats": {"tf": 1.4142135623730951}}, "df": 1}}}, "u": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"ffmpeg_bitrate_stats.BitrateStatsSummary.num_frames": {"tf": 1}}, "df": 1}}}}}}, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.calculate_statistics": {"tf": 1}}, "df": 1}}}}}, "j": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.print_statistics": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.get_json": {"tf": 1.4142135623730951}}, "df": 2}}}}, "g": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.get_csv": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStats.get_json": {"tf": 1}}, "df": 2}}}, "w": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {"ffmpeg_bitrate_stats.BitrateStats.plot": {"tf": 1.4142135623730951}}, "df": 1}}}}}, "k": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "/": {"docs": {}, "df": 0, "s": {"docs": {"ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.avg_bitrate_over_chunks": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.max_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.min_bitrate": {"tf": 1}, "ffmpeg_bitrate_stats.BitrateStatsSummary.bitrate_per_chunk": {"tf": 1}}, "df": 5}}}}}}}}}, "pipeline": ["trimmer"], "_isPrebuiltIndex": true}; 4 | 5 | // mirrored in build-search-index.js (part 1) 6 | // Also split on html tags. this is a cheap heuristic, but good enough. 7 | elasticlunr.tokenizer.setSeperator(/[\s\-.;&_'"=,()]+|<[^>]*>/); 8 | 9 | let searchIndex; 10 | if (docs._isPrebuiltIndex) { 11 | console.info("using precompiled search index"); 12 | searchIndex = elasticlunr.Index.load(docs); 13 | } else { 14 | console.time("building search index"); 15 | // mirrored in build-search-index.js (part 2) 16 | searchIndex = elasticlunr(function () { 17 | this.pipeline.remove(elasticlunr.stemmer); 18 | this.pipeline.remove(elasticlunr.stopWordFilter); 19 | this.addField("qualname"); 20 | this.addField("fullname"); 21 | this.addField("annotation"); 22 | this.addField("default_value"); 23 | this.addField("signature"); 24 | this.addField("bases"); 25 | this.addField("doc"); 26 | this.setRef("fullname"); 27 | }); 28 | for (let doc of docs) { 29 | searchIndex.addDoc(doc); 30 | } 31 | console.timeEnd("building search index"); 32 | } 33 | 34 | return (term) => searchIndex.search(term, { 35 | fields: { 36 | qualname: {boost: 4}, 37 | fullname: {boost: 2}, 38 | annotation: {boost: 2}, 39 | default_value: {boost: 2}, 40 | signature: {boost: 2}, 41 | bases: {boost: 2}, 42 | doc: {boost: 1}, 43 | }, 44 | expand: true 45 | }); 46 | })(); -------------------------------------------------------------------------------- /ffmpeg_bitrate_stats/__init__.py: -------------------------------------------------------------------------------- 1 | from .bitrate_stats import BitrateStats, BitrateStatsSummary, run_command 2 | 3 | __version__ = "1.1.2" 4 | 5 | __all__ = ["BitrateStats", "BitrateStatsSummary", "run_command"] 6 | -------------------------------------------------------------------------------- /ffmpeg_bitrate_stats/__main__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Calculate bitrate stats from video 4 | # 5 | # Output is in kilobit per second unless specified otherwise. 6 | # 7 | # Author: Werner Robitza 8 | # License: MIT 9 | 10 | import argparse 11 | import logging 12 | import os 13 | import sys 14 | from typing import Tuple 15 | 16 | from .__init__ import __version__ as version 17 | from .bitrate_stats import BitrateStats 18 | from .log import CustomLogFormatter 19 | 20 | logger = logging.getLogger("ffmpeg-bitrate-stats") 21 | 22 | 23 | def get_terminal_size() -> Tuple[int, int]: 24 | try: 25 | term_size = os.get_terminal_size() 26 | return (term_size.columns, term_size.lines) 27 | except OSError: 28 | return (80, 24) 29 | 30 | 31 | def setup_logger(level: int = logging.INFO) -> logging.Logger: 32 | logger = logging.getLogger("ffmpeg-bitrate-stats") 33 | logger.setLevel(level) 34 | 35 | ch = logging.StreamHandler(sys.stderr) 36 | ch.setLevel(level) 37 | 38 | ch.setFormatter(CustomLogFormatter()) 39 | 40 | logger.addHandler(ch) 41 | 42 | return logger 43 | 44 | 45 | def main() -> None: 46 | parser = argparse.ArgumentParser( 47 | formatter_class=argparse.ArgumentDefaultsHelpFormatter, 48 | description="ffmpeg_bitrate_stats v" + version, 49 | ) 50 | parser.add_argument("input", help="input file") 51 | 52 | parser.add_argument( 53 | "-n", 54 | "--dry-run", 55 | action="store_true", 56 | help="Do not run command, just show what would be done", 57 | ) 58 | 59 | parser.add_argument( 60 | "-v", "--verbose", action="store_true", help="Show verbose output" 61 | ) 62 | 63 | parser.add_argument( 64 | "-s", 65 | "--stream-type", 66 | default="video", 67 | choices=["video", "audio"], 68 | help="Stream type to analyze", 69 | ) 70 | 71 | parser.add_argument( 72 | "-a", 73 | "--aggregation", 74 | default="time", 75 | choices=["time", "gop"], 76 | help="Window for aggregating statistics, either time-based (per-second) or per GOP", 77 | ) 78 | 79 | parser.add_argument( 80 | "-c", 81 | "--chunk-size", 82 | type=float, 83 | default=1.0, 84 | help="Custom aggregation window size in seconds", 85 | ) 86 | 87 | parser.add_argument( 88 | "-rs", 89 | "--read-start", 90 | type=str, 91 | default=None, 92 | help="Time to wait before sampling video (in HH:MM:SS.msec or seconds)", 93 | ) 94 | parser.add_argument( 95 | "-rd", 96 | "--read-duration", 97 | type=str, 98 | default=None, 99 | help="Duration for sampling stream (in HH:MM:SS.msec or seconds). Note that seeking is not accurate, see ffprobe documentation on '-read_intervals'.", 100 | ) 101 | 102 | parser.add_argument( 103 | "-of", 104 | "--output-format", 105 | type=str, 106 | default="json", 107 | choices=["json", "csv"], 108 | help="output in which format", 109 | ) 110 | 111 | parser.add_argument( 112 | "-p", 113 | "--plot", 114 | action="store_true", 115 | help="Plot the bitrate over time (to STDERR)", 116 | ) 117 | 118 | parser.add_argument( 119 | "-pw", 120 | "--plot-width", 121 | type=int, 122 | default=max(get_terminal_size()[0] - 10, 10), 123 | help="Plot width", 124 | ) 125 | parser.add_argument( 126 | "-ph", 127 | "--plot-height", 128 | type=int, 129 | default=max(get_terminal_size()[1] - 6, 10), 130 | help="Plot height", 131 | ) 132 | 133 | cli_args = parser.parse_args() 134 | 135 | setup_logger(logging.DEBUG if cli_args.verbose else logging.INFO) 136 | 137 | br = BitrateStats( 138 | cli_args.input, 139 | stream_type=cli_args.stream_type, 140 | aggregation=cli_args.aggregation, 141 | chunk_size=cli_args.chunk_size, 142 | read_start=cli_args.read_start, 143 | read_duration=cli_args.read_duration, 144 | dry_run=cli_args.dry_run, 145 | ) 146 | br.calculate_statistics() 147 | br.print_statistics(cli_args.output_format) 148 | 149 | if cli_args.plot: 150 | br.plot( 151 | width=cli_args.plot_width, 152 | height=cli_args.plot_height, 153 | ) 154 | 155 | 156 | if __name__ == "__main__": 157 | main() 158 | -------------------------------------------------------------------------------- /ffmpeg_bitrate_stats/bitrate_stats.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import json 4 | import logging 5 | import math 6 | import subprocess 7 | import sys 8 | from typing import Any, List, Literal, Optional, TypedDict, cast 9 | 10 | import numpy as np 11 | import pandas as pd 12 | import plotille 13 | 14 | logger = logging.getLogger("ffmpeg-bitrate-stats") 15 | 16 | 17 | def run_command( 18 | cmd: List[str], dry_run: bool = False 19 | ) -> tuple[str, str] | tuple[None, None]: 20 | """ 21 | Run a command directly 22 | """ 23 | 24 | # for verbose mode 25 | logger.debug("[cmd] " + " ".join(cmd)) 26 | 27 | if dry_run: 28 | logger.info("[cmd] " + " ".join(cmd)) 29 | return None, None 30 | 31 | process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 32 | stdout, stderr = process.communicate() 33 | 34 | if process.returncode == 0: 35 | return stdout.decode("utf-8"), stderr.decode("utf-8") 36 | else: 37 | logger.error("error running command: {}".format(" ".join(cmd))) 38 | logger.error(stderr.decode("utf-8")) 39 | sys.exit(1) 40 | 41 | 42 | StreamType = Literal["audio", "video"] 43 | Aggregation = Literal["time", "gop"] 44 | 45 | 46 | class FrameEntry(TypedDict): 47 | n: int 48 | frame_type: Literal["I", "Non-I"] 49 | pts: float | Literal["NaN"] 50 | size: int 51 | duration: float | Literal["NaN"] 52 | 53 | 54 | class BitrateStatsSummary(TypedDict): 55 | input_file: str 56 | """ 57 | The input file. 58 | """ 59 | stream_type: StreamType 60 | """ 61 | The stream type (audio/video). 62 | """ 63 | avg_fps: float 64 | """ 65 | The average FPS. 66 | """ 67 | num_frames: int 68 | """ 69 | The number of frames. 70 | """ 71 | avg_bitrate: float 72 | """ 73 | The average bitrate in kbit/s. 74 | """ 75 | avg_bitrate_over_chunks: float 76 | """ 77 | The average bitrate in kbit/s over chunks. 78 | """ 79 | max_bitrate: float 80 | """ 81 | The maximum bitrate in kbit/s. 82 | """ 83 | min_bitrate: float 84 | """ 85 | The minimum bitrate in kbit/s. 86 | """ 87 | max_bitrate_factor: float 88 | """ 89 | Relation between peak and average. 90 | """ 91 | bitrate_per_chunk: list[float] 92 | """ 93 | The bitrate per chunk in kbit/s. 94 | """ 95 | aggregation: Aggregation 96 | """ 97 | The aggregation type (time/chunks). 98 | """ 99 | chunk_size: Optional[int] 100 | """ 101 | The chunk size in seconds. 102 | """ 103 | duration: float 104 | """ 105 | The duration in seconds. 106 | """ 107 | 108 | 109 | class BitrateStats: 110 | """ 111 | Initialize the BitrateStats class. 112 | 113 | Args: 114 | input_file (str): Path to the input file 115 | stream_type (str, optional): Stream type (audio/video). Defaults to "video". 116 | aggregation (str, optional): Aggregation type (time/gop). Defaults to "time". 117 | chunk_size (int, optional): Chunk size. Defaults to 1. 118 | read_start (str, optional): Start time for reading in HH:MM:SS.msec or seconds. Defaults to None. 119 | read_duration (str, optional): Duration for reading in HH:MM:SS.msec or seconds. Defaults to None. 120 | dry_run (bool, optional): Dry run. Defaults to False. 121 | """ 122 | 123 | def __init__( 124 | self, 125 | input_file: str, 126 | stream_type: StreamType = "video", 127 | aggregation: Aggregation = "time", 128 | chunk_size: int = 1, 129 | read_start: Optional[str] = None, 130 | read_duration: Optional[str] = None, 131 | dry_run: bool = False, 132 | ): 133 | self.input_file = input_file 134 | 135 | if stream_type not in ["audio", "video"]: 136 | raise ValueError("Stream type must be audio/video") 137 | self.stream_type: StreamType = stream_type 138 | 139 | if aggregation not in ["time", "gop"]: 140 | raise ValueError("Wrong aggregation type") 141 | if aggregation == "gop" and stream_type == "audio": 142 | raise ValueError("GOP aggregation for audio does not make sense") 143 | self.aggregation: Aggregation = aggregation 144 | 145 | if chunk_size and chunk_size < 0: 146 | raise ValueError("Chunk size must be greater than 0") 147 | self.chunk_size = chunk_size 148 | 149 | self.read_length: Optional[str] = None 150 | if read_start or read_duration: 151 | self.read_length = "{}%{}".format( 152 | f"+{read_start}" if read_start else "", 153 | f"+{read_duration}" if read_duration else "", 154 | ) 155 | 156 | self.dry_run = dry_run 157 | 158 | self.duration: float = 0 159 | self.fps: float = 0 160 | self.max_bitrate: float = 0 161 | self.min_bitrate: float = 0 162 | self.moving_avg_bitrate: list[float] = [] 163 | self.frames: list[FrameEntry] = [] 164 | self.bitrate_stats: BitrateStatsSummary | None = None 165 | 166 | self.rounding_factor: int = 3 167 | 168 | self._gop_start_times: Optional[list[float]] = None 169 | self._chunks: list[float] = [] 170 | 171 | def calculate_statistics(self) -> BitrateStatsSummary: 172 | """ 173 | Calculate the bitrate statistics. 174 | 175 | Raises: 176 | RuntimeError: If an error occurred. 177 | 178 | Returns: 179 | dict: The bitrate statistics summary. 180 | """ 181 | self._calculate_frame_sizes() 182 | self._calculate_duration() 183 | self._calculate_fps() 184 | self._calculate_max_min_bitrate() 185 | self._assemble_bitrate_statistics() 186 | 187 | if self.bitrate_stats is None: 188 | raise RuntimeError("bitrate_stats is None, should not happen") 189 | 190 | return self.bitrate_stats 191 | 192 | def _calculate_frame_sizes(self) -> list[FrameEntry]: 193 | """ 194 | Get the frame sizes via ffprobe using the -show_packets option. 195 | This includes the NAL headers, of course. 196 | 197 | Returns: 198 | list[dict]: The frame sizes plus some extra info. 199 | """ 200 | logger.debug(f"Calculating frame size from {self.input_file}") 201 | 202 | base_cmd = [ 203 | "ffprobe", 204 | "-loglevel", 205 | "error", 206 | "-select_streams", 207 | self.stream_type[0] + ":0", 208 | ] 209 | 210 | if self.read_length: 211 | base_cmd.extend(["-read_intervals", self.read_length]) 212 | 213 | base_cmd.extend( 214 | [ 215 | "-show_packets", 216 | "-show_entries", 217 | "packet=pts_time,dts_time,duration_time,size,flags", 218 | "-of", 219 | "json", 220 | self.input_file, 221 | ] 222 | ) 223 | 224 | stdout, _ = run_command(base_cmd, self.dry_run) 225 | if self.dry_run or stdout is None: 226 | logger.error("Aborting prematurely, dry-run specified or stdout was empty") 227 | sys.exit(0) 228 | 229 | info = json.loads(stdout)["packets"] 230 | # abort if nothing returned 231 | if not info: 232 | raise RuntimeError( 233 | "No frames returned, please check your input file and the ffprobe output. Run with -v to see the ffprobe command." 234 | ) 235 | 236 | ret: list[FrameEntry] = [] 237 | idx = 1 238 | 239 | default_duration = next( 240 | (x["duration_time"] for x in info if "duration_time" in x.keys()), "NaN" 241 | ) 242 | 243 | for packet_info in info: 244 | frame_type: Literal["I", "Non-I"] = ( 245 | # key frames are marked with a capital K (K_ or K__) in packet flags 246 | "I" if "K" in packet_info["flags"] else "Non-I" 247 | ) 248 | 249 | pts: float | Literal["NaN"] = ( 250 | float(packet_info["pts_time"]) 251 | if "pts_time" in packet_info.keys() 252 | else "NaN" 253 | ) 254 | 255 | duration: float | Literal["NaN"] = ( 256 | float(packet_info["duration_time"]) 257 | if "duration_time" in packet_info.keys() 258 | else float(default_duration) 259 | if default_duration != "NaN" 260 | else "NaN" 261 | ) 262 | 263 | ret.append( 264 | { 265 | "n": idx, 266 | "frame_type": frame_type, 267 | "pts": pts, 268 | "size": int(packet_info["size"]), 269 | "duration": duration, 270 | } 271 | ) 272 | idx += 1 273 | 274 | # fix for missing durations, estimate it via PTS 275 | if default_duration == "NaN": 276 | ret = self._fix_durations(ret) 277 | 278 | # fix missing data in first packet (occurs occassionally when reading streams) 279 | if ret[0]["duration"] == "NaN" and isinstance(ret[1]["duration"], float): 280 | ret[0]["duration"] = ret[1]["duration"] 281 | 282 | if ( 283 | ret[0]["pts"] == "NaN" 284 | and isinstance(ret[1]["pts"], float) 285 | and isinstance(ret[0]["duration"], float) 286 | ): 287 | ret[0]["pts"] = ret[1]["pts"] - ret[0]["duration"] 288 | 289 | self.frames = ret 290 | return ret 291 | 292 | def _fix_durations(self, ret: List[FrameEntry]) -> List[FrameEntry]: 293 | """ 294 | Calculate durations based on delta PTS. 295 | """ 296 | last_duration = None 297 | for i in range(len(ret) - 1): 298 | curr_pts = ret[i]["pts"] 299 | next_pts = ret[i + 1]["pts"] 300 | if curr_pts == "NaN" or next_pts == "NaN": 301 | logger.warning("PTS is NaN, duration/bitrate may be invalid") 302 | continue 303 | if next_pts < curr_pts: 304 | logger.warning( 305 | "Non-monotonically increasing PTS, duration/bitrate may be invalid" 306 | ) 307 | last_duration = next_pts - curr_pts 308 | ret[i]["duration"] = last_duration 309 | if last_duration is not None: 310 | ret[-1]["duration"] = last_duration 311 | return ret 312 | 313 | def _calculate_duration(self) -> float: 314 | """ 315 | Sum of all duration entries. 316 | 317 | Returns: 318 | float: The duration in seconds. 319 | """ 320 | self.duration = sum( 321 | f["duration"] for f in self.frames if f["duration"] != "NaN" 322 | ) 323 | return self.duration 324 | 325 | def _calculate_fps(self) -> float: 326 | """ 327 | FPS = number of frames divided by duration. A rough estimate. 328 | 329 | Returns: 330 | float: The FPS. 331 | """ 332 | self.fps = len(self.frames) / self.duration 333 | return self.fps 334 | 335 | def _collect_chunks(self) -> list[float]: 336 | """ 337 | Collect chunks of a certain aggregation length (in seconds, or GOP). 338 | This is cached. 339 | 340 | Returns: 341 | list[float]: The bitrate values per chunk in kbit/s. 342 | """ 343 | if len(self._chunks): 344 | return self._chunks 345 | 346 | logger.debug("Collecting chunks for bitrate calculation") 347 | 348 | # this is where we will store the stats in buckets 349 | aggregation_chunks: list[list[FrameEntry]] = [] 350 | curr_list: list[FrameEntry] = [] 351 | 352 | self._gop_start_times = [] 353 | 354 | if self.aggregation == "gop": 355 | # collect group of pictures, each one containing all frames belonging to it 356 | for frame in self.frames: 357 | if frame["frame_type"] != "I": 358 | curr_list.append(frame) 359 | if frame["frame_type"] == "I": 360 | if curr_list: 361 | aggregation_chunks.append(curr_list) 362 | curr_list = [frame] 363 | self._gop_start_times.append(float(frame["pts"])) 364 | # flush the last one 365 | aggregation_chunks.append(curr_list) 366 | 367 | else: 368 | # per-time aggregation 369 | agg_time: float = 0 370 | for frame in self.frames: 371 | if agg_time < self.chunk_size: 372 | curr_list.append(frame) 373 | agg_time += float(frame["duration"]) 374 | else: 375 | if curr_list: 376 | aggregation_chunks.append(curr_list) 377 | curr_list = [frame] 378 | agg_time = float(frame["duration"]) 379 | aggregation_chunks.append(curr_list) 380 | 381 | # calculate BR per group 382 | self._chunks = [ 383 | BitrateStats._bitrate_for_frame_list(x) for x in aggregation_chunks 384 | ] 385 | 386 | return self._chunks 387 | 388 | @staticmethod 389 | def _bitrate_for_frame_list(frame_list: list[FrameEntry]) -> float: 390 | """ 391 | Given a list of frames with size and PTS, get the bitrate. 392 | 393 | Args: 394 | frame_list (list): list of frames 395 | 396 | Returns: 397 | float: bitrate in kbit/s 398 | """ 399 | if len(frame_list) < 2: 400 | return math.nan 401 | 402 | # sort frames by PTS in case they are unordered 403 | frame_list.sort(key=lambda x: x["pts"]) 404 | 405 | duration = float(frame_list[-1]["pts"]) - float(frame_list[0]["pts"]) 406 | size = sum(f["size"] for f in frame_list) 407 | bitrate = ((size * 8) / 1000) / duration 408 | 409 | return bitrate 410 | 411 | def _calculate_max_min_bitrate(self) -> tuple[float, float]: 412 | """ 413 | Find the min/max from the chunks. 414 | 415 | Returns: 416 | tuple: max, min bitrate in kbit/s 417 | """ 418 | self.max_bitrate = max(self._collect_chunks()) 419 | self.min_bitrate = min(self._collect_chunks()) 420 | return self.max_bitrate, self.min_bitrate 421 | 422 | def _assemble_bitrate_statistics(self) -> BitrateStatsSummary: 423 | """ 424 | Assemble all pre-calculated statistics plus some simple statistical measures. 425 | 426 | Returns: 427 | dict: bitrate statistics 428 | """ 429 | 430 | self.avg_bitrate = ( 431 | sum(f["size"] for f in self.frames) * 8 / 1000 432 | ) / self.duration 433 | self.avg_bitrate_over_chunks: float = cast( 434 | float, np.mean(self._collect_chunks()) 435 | ) 436 | 437 | self.max_bitrate_factor = self.max_bitrate / self.avg_bitrate 438 | 439 | # output data 440 | ret: BitrateStatsSummary = { 441 | "input_file": self.input_file, 442 | "stream_type": self.stream_type, 443 | "avg_fps": round(self.fps, self.rounding_factor), 444 | "num_frames": len(self.frames), 445 | "avg_bitrate": round(self.avg_bitrate, self.rounding_factor), 446 | "avg_bitrate_over_chunks": round( 447 | self.avg_bitrate_over_chunks, self.rounding_factor 448 | ), 449 | "max_bitrate": round(self.max_bitrate, self.rounding_factor), 450 | "min_bitrate": round(self.min_bitrate, self.rounding_factor), 451 | "max_bitrate_factor": round(self.max_bitrate_factor, self.rounding_factor), 452 | "bitrate_per_chunk": [ 453 | round(b, self.rounding_factor) for b in self._collect_chunks() 454 | ], 455 | "aggregation": self.aggregation, 456 | "chunk_size": self.chunk_size if self.aggregation == "time" else None, 457 | "duration": round(self.duration, self.rounding_factor), 458 | } 459 | 460 | self.bitrate_stats = ret 461 | return self.bitrate_stats 462 | 463 | def print_statistics(self, output_format: Literal["csv", "json"]) -> None: 464 | """ 465 | Print the statistics in the specified format to stdout. 466 | 467 | Args: 468 | output_format: The format to print the statistics in (csv, json) 469 | 470 | Raises: 471 | ValueError: If the output format is invalid 472 | """ 473 | if output_format == "csv": 474 | print(self.get_csv()) 475 | elif output_format == "json": 476 | print(self.get_json()) 477 | else: 478 | raise ValueError("Invalid output format") 479 | 480 | def get_csv(self) -> str: 481 | """ 482 | Get the bitrate statistics as a CSV string. 483 | 484 | Raises: 485 | RuntimeError: If no bitrate statistics are available 486 | 487 | Returns: 488 | str: The bitrate statistics as a CSV string 489 | """ 490 | if not self.bitrate_stats: 491 | raise RuntimeError("No bitrate stats available") 492 | 493 | df = pd.DataFrame(self.bitrate_stats) 494 | df.reset_index(level=0, inplace=True) 495 | df.rename(index=str, columns={"index": "chunk_index"}, inplace=True) 496 | cols = df.columns.tolist() 497 | cols.insert(0, cols.pop(cols.index("input_file"))) 498 | df = df.reindex(columns=cols) 499 | return cast(str, df.to_csv(index=False)) 500 | 501 | def get_json(self) -> str: 502 | """ 503 | Get the bitrate statistics as a JSON string. 504 | 505 | Raises: 506 | RuntimeError: If no bitrate statistics are available 507 | 508 | Returns: 509 | str: The bitrate statistics as a JSON string 510 | """ 511 | if not self.bitrate_stats: 512 | raise RuntimeError("No bitrate stats available") 513 | 514 | return json.dumps(self.bitrate_stats, indent=4) 515 | 516 | def plot(self, width: int = 80, height: int = 30) -> None: 517 | """ 518 | Plot the bitrate over time to STDERR. 519 | 520 | Args: 521 | width (int, optional): Width of the plot. Defaults to 80. 522 | height (int, optional): Height of the plot. Defaults to 30. 523 | """ 524 | chunks = self._collect_chunks() 525 | 526 | fig = plotille.Figure() 527 | fig.width = width 528 | fig.height = height 529 | 530 | def _round_decimals( 531 | val: Any, chars: int, delta: float, left: bool = False 532 | ) -> str: 533 | align = "<" if left else "" 534 | return f"{val:{align}{chars}.{self.rounding_factor}f}" 535 | 536 | x_values = ( 537 | self._gop_start_times 538 | if self.aggregation == "gop" 539 | else [i * self.chunk_size for i in range(len(chunks))] 540 | ) 541 | 542 | fig.register_label_formatter(int, _round_decimals) 543 | fig.register_label_formatter(float, _round_decimals) 544 | fig.set_x_limits(min_=0, max_=self.duration) 545 | fig.set_y_limits(min_=0) 546 | fig.x_label = "Time (s)" 547 | fig.y_label = "Bitrate (kbit/s)" 548 | 549 | fig.plot( 550 | x_values, 551 | chunks, 552 | ) 553 | 554 | print(fig.show(), file=sys.stderr) 555 | -------------------------------------------------------------------------------- /ffmpeg_bitrate_stats/log.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | 4 | class CustomLogFormatter(logging.Formatter): 5 | """ 6 | https://stackoverflow.com/a/56944256/435093 7 | """ 8 | 9 | grey = "\x1b[38;20m" 10 | yellow = "\x1b[33;20m" 11 | red = "\x1b[31;20m" 12 | bold_red = "\x1b[31;1m" 13 | reset = "\x1b[0m" 14 | # strformat = ( 15 | # "%(asctime)s - %(name)s - %(levelname)s - %(message)s (%(filename)s:%(lineno)d)" 16 | # ) 17 | strformat = "%(levelname)s - %(message)s" 18 | 19 | FORMATS = { 20 | logging.DEBUG: grey + strformat + reset, 21 | logging.INFO: grey + strformat + reset, 22 | logging.WARNING: yellow + strformat + reset, 23 | logging.ERROR: red + strformat + reset, 24 | logging.CRITICAL: bold_red + strformat + reset, 25 | } 26 | 27 | def format(self, record: logging.LogRecord) -> str: 28 | log_fmt = self.FORMATS.get(record.levelno) 29 | formatter = logging.Formatter(log_fmt) 30 | return formatter.format(record) 31 | -------------------------------------------------------------------------------- /ffmpeg_bitrate_stats/py.typed: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/slhck/ffmpeg-bitrate-stats/fdb1a170f92f2c5fe5a78605a78d9acd4493911a/ffmpeg_bitrate_stats/py.typed -------------------------------------------------------------------------------- /requirements.dev.txt: -------------------------------------------------------------------------------- 1 | pytest>=6.2.2 2 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | numpy 2 | pandas 3 | plotille 4 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [mypy] 2 | mypy_path = ffmpeg_bitrate_stats 3 | exclude = build 4 | namespace_packages = False 5 | ignore_missing_imports = True 6 | disallow_untyped_defs = True 7 | no_implicit_optional = True 8 | check_untyped_defs = True 9 | warn_return_any = True 10 | warn_unused_ignores = True 11 | show_error_codes = True 12 | 13 | [wheel] 14 | universal = 1 15 | 16 | [flake8] 17 | max-line-length = 160 18 | 19 | [tox:tox] 20 | envlist = py38,py39,py310,py311,mypy,lint 21 | 22 | [testenv] 23 | deps = 24 | -r requirements.txt 25 | -r requirements.dev.txt 26 | commands = pytest test/test.py 27 | 28 | [testenv:mypy] 29 | deps = mypy 30 | commands = mypy ffmpeg_bitrate_stats 31 | 32 | [testenv:lint] 33 | deps = flake8 34 | commands = flake8 . --count 35 | 36 | [gh-actions] 37 | python = 38 | 3.8: py38 39 | 3.9: py39 40 | 3.10: py310 41 | 3.11: py311, mypy, lint 42 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # Always prefer setuptools over distutils 2 | import os 3 | 4 | # To use a consistent encoding 5 | from codecs import open 6 | 7 | from setuptools import setup 8 | 9 | here = os.path.abspath(os.path.dirname(__file__)) 10 | 11 | # Versioning 12 | with open(os.path.join(here, "ffmpeg_bitrate_stats", "__init__.py")) as version_file: 13 | for line in version_file: 14 | if line.startswith("__version__"): 15 | version = eval(line.split(" = ")[1]) 16 | break 17 | 18 | # Get the long description from the README file 19 | with open(os.path.join(here, "README.md"), encoding="utf-8") as f: 20 | long_description = f.read() 21 | 22 | setup( 23 | name="ffmpeg_bitrate_stats", 24 | version=version, 25 | description="Calculate bitrate statistics using FFmpeg", 26 | long_description=long_description, 27 | long_description_content_type="text/markdown", 28 | url="https://github.com/slhck/ffmpeg-bitrate-stats", 29 | author="Werner Robitza", 30 | author_email="werner.robitza@gmail.com", 31 | license="MIT", 32 | classifiers=[ 33 | "Development Status :: 4 - Beta", 34 | "Intended Audience :: Developers", 35 | "Topic :: Multimedia :: Video", 36 | "License :: OSI Approved :: MIT License", 37 | "Programming Language :: Python :: 3", 38 | "Programming Language :: Python :: 3.8", 39 | "Programming Language :: Python :: 3.9", 40 | "Programming Language :: Python :: 3.10", 41 | "Programming Language :: Python :: 3.11", 42 | ], 43 | python_requires=">=3.8", 44 | packages=["ffmpeg_bitrate_stats"], 45 | install_requires=["numpy", "pandas", "plotille"], 46 | include_package_data=True, 47 | package_data={ 48 | "ffmpeg_bitrate_stats": ["py.typed"], 49 | }, 50 | entry_points={ 51 | "console_scripts": [ 52 | "ffmpeg-bitrate-stats=ffmpeg_bitrate_stats.__main__:main", 53 | ], 54 | }, 55 | ) 56 | -------------------------------------------------------------------------------- /test/test.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/slhck/ffmpeg-bitrate-stats/fdb1a170f92f2c5fe5a78605a78d9acd4493911a/test/test.mp4 -------------------------------------------------------------------------------- /test/test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env pytest 2 | 3 | import json 4 | import os 5 | import sys 6 | 7 | sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) 8 | 9 | from ffmpeg_bitrate_stats import run_command # noqa: E402 10 | 11 | test_files = { 12 | "test.mp4": { 13 | "params": [], 14 | "results": { 15 | "stream_type": "video", 16 | "avg_fps": 25.0, 17 | "num_frames": 25, 18 | "avg_bitrate": 58.944, 19 | "avg_bitrate_over_chunks": 61.4, 20 | "max_bitrate": 61.4, 21 | "min_bitrate": 61.4, 22 | "max_bitrate_factor": 1.042, 23 | "bitrate_per_chunk": [61.4], 24 | "aggregation": "time", 25 | "chunk_size": 1.0, 26 | "duration": 1.0, 27 | }, 28 | }, 29 | "without_timestamps.mp4": { 30 | "params": [], 31 | "results": { 32 | "stream_type": "video", 33 | "avg_fps": 25.0, 34 | "num_frames": 25, 35 | "avg_bitrate": 111.128, 36 | "avg_bitrate_over_chunks": 115.758, 37 | "max_bitrate": 115.758, 38 | "min_bitrate": 115.758, 39 | "max_bitrate_factor": 1.042, 40 | "bitrate_per_chunk": [115.758], 41 | "aggregation": "time", 42 | "chunk_size": 1.0, 43 | "duration": 1.0, 44 | }, 45 | }, 46 | "test_keyframes.mp4": { 47 | "params": ["-a", "gop"], 48 | "results": { 49 | "stream_type": "video", 50 | "avg_fps": 50.0, 51 | "num_frames": 5, 52 | "avg_bitrate": 14813.6, 53 | "avg_bitrate_over_chunks": 9258.5, 54 | "max_bitrate": 9258.5, 55 | "min_bitrate": 9258.5, 56 | "max_bitrate_factor": 0.625, 57 | "bitrate_per_chunk": [9258.5], 58 | "aggregation": "gop", 59 | "chunk_size": None, 60 | "duration": 0.1, 61 | }, 62 | }, 63 | } 64 | 65 | 66 | class TestBitrates: 67 | def test_output(self) -> None: 68 | """ 69 | Simple test for CLI functionality 70 | """ 71 | 72 | for test_filename, expected_output in test_files.items(): 73 | test_file = os.path.abspath( 74 | os.path.join(os.path.dirname(__file__), test_filename) 75 | ) 76 | 77 | stdout, _ = run_command( 78 | [ 79 | "python3", 80 | "-m", 81 | "ffmpeg_bitrate_stats", 82 | test_file, 83 | *expected_output["params"], 84 | ] 85 | ) 86 | 87 | assert stdout is not None 88 | 89 | output = json.loads(stdout) 90 | 91 | assert test_filename in output["input_file"] 92 | 93 | del output["input_file"] 94 | 95 | assert output == expected_output["results"] 96 | -------------------------------------------------------------------------------- /test/test_keyframes.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/slhck/ffmpeg-bitrate-stats/fdb1a170f92f2c5fe5a78605a78d9acd4493911a/test/test_keyframes.mp4 -------------------------------------------------------------------------------- /test/without_timestamps.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/slhck/ffmpeg-bitrate-stats/fdb1a170f92f2c5fe5a78605a78d9acd4493911a/test/without_timestamps.mp4 --------------------------------------------------------------------------------