[
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: CI\n\non:\n  push:\n    branches:\n      - master\n  pull_request:\n    branches:\n      - master\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n\n    strategy:\n      matrix:\n        python-version: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12']\n\n    steps:\n    - name: Checkout Repository\n      uses: actions/checkout@v2\n\n    - name: Set up Python ${{ matrix.python-version }}\n      uses: actions/setup-python@v2\n      with:\n        python-version: ${{ matrix.python-version }}\n\n    - name: Install tox\n      run: pip install tox\n\n    - name: Run tox\n      run: tox\n\n    - name: Upload coverage reports to Codecov\n      uses: codecov/codecov-action@v4.0.1\n      with:\n        token: ${{ secrets.CODECOV_TOKEN }}\n        file: coverage.xml"
  },
  {
    "path": ".gitignore",
    "content": "# Compiled files\n__pycache__/\n*.pyc\n\n# Distribution\n*.egg-info\n.eggs/\nbuild/\ndist/\n\n# Testing\n.tox/\n\n# PyCharm\n.idea\n\n# Documentation\ndocs/_build/"
  },
  {
    "path": ".readthedocs.yaml",
    "content": "version: \"2\"\n\nbuild:\n  os: \"ubuntu-22.04\"\n  tools:\n    python: \"3.12\"\n\nsphinx:\n  configuration: docs/source/conf.py\n\npython:\n   install:\n   - requirements: docs/requirements.txt\n   - method: pip\n     path: ."
  },
  {
    "path": "CHANGELOG.rst",
    "content": "History\n=======\n\n0.5.1 (30-05-2024)\n------------------\n\n* Added voice span support (#55)\n* Extended from_buffer support to allow BytesIO and also other format conversions (#32)\n* Fixed save SRT to not include cue tags, thanks to `@lilaboc <https://github.com/lilaboc>`_ (#56)\n* Fixed saved caption to include a line break after the last caption as per standard (#49)\n\n0.5.0 (15-05-2024)\n------------------\n\n* Added styles support\n* Added comments support\n* Added from_string\n* Added iterate over a slice of captions\n* Refactor of the library\n* Parser is no longer strict and ignores malformed blocks\n* Improved BOM support allowing to keep the BOM or remove it\n* Deprecated read_buffer in favor of from_buffer\n* Removed support for old versions of Python: 3.4, 3.5 and 3.6\n\n0.4.6 (18-11-2020)\n------------------\n\n* Add capability to get WebVTT formatted content without an output file, thanks to `@DawoudSheraz <https://github.com/DawoudSheraz>`_ (#34)\n* Add Python 3.9 support\n\n0.4.5 (09-04-2020)\n------------------\n\n* Fix issue reading buffer\n\n0.4.4 (27-03-2020)\n------------------\n\n* Allow parsing empty SBV captions, thanks to `@ishunyu <https://github.com/ishunyu>`_ (#26)\n* Fix invalid time cues, thanks to `@sontek <https://github.com/sontek>`_ (#19)\n* Enable pytest as test runner, thanks to `@sontek <https://github.com/sontek>`_ (#20)\n* Packaging improvements\n* Added Python 3.8 support\n* Improve parsing empty lines\n\n0.4.3 (22-11-2019)\n------------------\n\n* Parsing improvements, thanks to `@sontek <https://github.com/sontek>`_ (#18)\n* Add support for reading content from a file-like object, thanks to `@omerholz <https://github.com/omerholz>`_ (#23)\n* Documentation fixes thanks to `@sontek <https://github.com/sontek>`_ (#22) and `@netcmcc <https://github.com/netcmcc>`_ (#24)\n\n0.4.2 (08-06-2018)\n------------------\n\n* Renamed and reorganized few of the modules\n* Parsing methods are now class methods: read, from_srt and from_sbv\n* Improved usability with the addition of shortcuts to avoid instantiating the classes so we can do:\n\nimport webvtt\n\nwebvtt.read('captions.vtt')  # this will return a WebVTT instance\n\n\n0.4.1 (24-12-2017)\n------------------\n\n* Support for saving cue identifiers\n\n0.4.0 (18-09-2017)\n------------------\n\nThe main goal of this release is a refactor of the WebVTT parser to be able to parse easier and give support to\nnew features of the format.\n\nNew features:\n\n* Support for cue identifiers\n* Support for parsing WebVTT captions with comments\n* Support for parsing WebVTT captions with Style blocks\n* Support for BOM in caption files\n* Added method to write the captions to an opened file\n* Convert WebVTT to SRT format\n* Ignore empty captions in SRT format\n\nOther:\n\n* Refactored WebVTT parser\n\n0.3.3 (23-08-2017)\n------------------\n\nThe text for the caption is now returned clean (tags removed). The cue text could contain tags like:\n* timestamp tags: *<00:19.000>*\n* class tags: *<c.classname>text</c>*\n* and others...\n**Important**: It currently removes any tag present in the cue text. For example <b> would be removed.\n\nAlso a new attribute is available on captions to retrieve the text without cleaning tags: **raw_text**\n\n0.3.2 (11-08-2017)\n------------------\n\nThe goal of this release if to allow the WebVTT parser to be able to read caption files that contain metadata headers\nthat extend to more than one line.\n\n0.3.1 (08-08-2017)\n------------------\n\n* Made hours in WebVTT parser optional as per specs.\n* Added support to parse WebVTT files that contain metadata headers.\n\n0.3.0 (02-06-2016)\n------------------\n\nNew features:\n\n* Added support for YouTube SBV captions.\n* Added easy iteration to WebVTT class.\n* New CLI command for segmenting captions for HLS.\n\nOther:\n\n* Improved parsers to reuse functionality.\n* Added an exception for invalid timestamps in captions.\n* Added an exception when saving without a filename.\n\n0.2.0 (23-05-2016)\n------------------\n\n* Refactor of the main module and parsers.\n\n\n0.1.0 (20-05-2016)\n------------------\n\nThis module is released with the following initial features:\n\n* Read/Edit/Write WebVTT captions.\n* Read SRT captions and convert to WebVTT.\n* Segment WebVTT files for captioning HLS video.\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2016 Alejandro Mendez\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE."
  },
  {
    "path": "MANIFEST.in",
    "content": "include LICENSE\ninclude README.rst\n\ngraft tests\n\nglobal-exclude __pycache__\nglobal-exclude *.py[co]\n"
  },
  {
    "path": "Makefile",
    "content": "build:\n\trm -rf dist\n\tmkdir dist\n\tpython setup.py sdist bdist_wheel\n\ttwine check dist/*\n\nrelease_test: build\n\ttwine upload -r testpypi dist/*\n\nrelease: build\n\ttwine upload dist/*\n\n.PHONY: build release_test release"
  },
  {
    "path": "README.rst",
    "content": "webvtt-py\n=========\n\n|pypi| |pyversions| |license| |coverage| |build-status| |docs-status| |downloads|\n\n``webvtt-py`` is a Python library for reading, writing and converting WebVTT_ caption files. It also features caption segmentation useful when captioning `HLS videos`_.\n\nDocumentation is available at http://webvtt-py.readthedocs.io.\n\n.. _`WebVTT`: https://www.w3.org/TR/webvtt1/\n.. _`HLS videos`: https://datatracker.ietf.org/doc/html/draft-pantos-hls-rfc8216bis\n\nInstallation\n------------\n\n::\n\n    $ pip install webvtt-py\n\nUsage\n-----\n\n.. code-block:: python\n\n  import webvtt\n\n  for caption in webvtt.read('captions.vtt'):\n      print(caption.identifier)  # cue identifier if any\n      print(caption.start)       # cue start time\n      print(caption.end)         # cue end time\n      print(caption.text)        # cue payload\n      print(caption.voice)       # cue voice span if any\n\nSegmenting for HLS\n------------------\n\n.. code-block:: python\n\n  import webvtt\n\n  webvtt.segment('captions.vtt', 'output/path')\n\nConverting captions from other formats\n--------------------------------------\n\nSupported formats:\n\n* SubRip (.srt)\n* YouTube SBV (.sbv)\n\n.. code-block:: python\n\n  import webvtt\n\n  webvtt = webvtt.from_srt('captions.srt')\n  webvtt.save()\n\n  # alternatively in a single line\n  webvtt.from_sbv('captions.sbv').save()\n\nCLI\n---\nCaption segmentation is also available from the command line:\n\n::\n\n    $ webvtt segment captions.vtt --output output/path\n\nLicense\n-------\n\nLicensed under the MIT License.\n\n.. |pypi| image:: https://img.shields.io/pypi/v/webvtt-py.svg\n    :target: https://pypi.python.org/pypi/webvtt-py\n\n.. |pyversions| image:: https://img.shields.io/pypi/pyversions/webvtt-py.svg\n    :alt: Supported Python versions\n    :target: https://pypi.python.org/pypi/webvtt-py\n\n.. |license| image:: https://img.shields.io/pypi/l/webvtt-py.svg\n    :alt: MIT License\n    :target: https://opensource.org/licenses/MIT\n\n.. |coverage| image:: https://codecov.io/gh/glut23/webvtt-py/graph/badge.svg?branch=master\n    :target: https://codecov.io/gh/glut23/webvtt-py\n\n.. |build-status| image:: https://github.com/glut23/webvtt-py/actions/workflows/ci.yml/badge.svg?branch=master\n    :target: https://github.com/glut23/webvtt-py/actions/workflows/ci.yml\n\n.. |docs-status| image:: https://readthedocs.org/projects/webvtt-py/badge/?version=latest\n    :target: http://webvtt-py.readthedocs.io/en/latest/?badge=latest\n    :alt: Documentation Status\n\n.. |downloads| image:: https://static.pepy.tech/badge/webvtt-py\n    :target: https://pepy.tech/project/webvtt-py\n    :alt: Downloads"
  },
  {
    "path": "docs/Makefile",
    "content": "# Minimal makefile for Sphinx documentation\n#\n\n# You can set these variables from the command line, and also\n# from the environment for the first two.\nSPHINXOPTS    ?=\nSPHINXBUILD   ?= sphinx-build\nSOURCEDIR     = source\nBUILDDIR      = build\n\n# Put it first so that \"make\" without argument is like \"make help\".\nhelp:\n\t@$(SPHINXBUILD) -M help \"$(SOURCEDIR)\" \"$(BUILDDIR)\" $(SPHINXOPTS) $(O)\n\n.PHONY: help Makefile\n\n# Catch-all target: route all unknown targets to Sphinx using the new\n# \"make mode\" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).\n%: Makefile\n\t@$(SPHINXBUILD) -M $@ \"$(SOURCEDIR)\" \"$(BUILDDIR)\" $(SPHINXOPTS) $(O)"
  },
  {
    "path": "docs/make.bat",
    "content": "@ECHO OFF\r\n\r\npushd %~dp0\r\n\r\nREM Command file for Sphinx documentation\r\n\r\nif \"%SPHINXBUILD%\" == \"\" (\r\n\tset SPHINXBUILD=sphinx-build\r\n)\r\nset SOURCEDIR=source\r\nset BUILDDIR=build\r\n\r\nif \"%1\" == \"\" goto help\r\n\r\n%SPHINXBUILD% >NUL 2>NUL\r\nif errorlevel 9009 (\r\n\techo.\r\n\techo.The 'sphinx-build' command was not found. Make sure you have Sphinx\r\n\techo.installed, then set the SPHINXBUILD environment variable to point\r\n\techo.to the full path of the 'sphinx-build' executable. Alternatively you\r\n\techo.may add the Sphinx directory to PATH.\r\n\techo.\r\n\techo.If you don't have Sphinx installed, grab it from\r\n\techo.http://sphinx-doc.org/\r\n\texit /b 1\r\n)\r\n\r\n%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%\r\ngoto end\r\n\r\n:help\r\n%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%\r\n\r\n:end\r\npopd"
  },
  {
    "path": "docs/requirements.txt",
    "content": "sphinx==7.3.7\nsphinx-rtd-theme==2.0.0"
  },
  {
    "path": "docs/source/conf.py",
    "content": "# Configuration file for the Sphinx documentation builder.\n\nimport sys\nfrom pathlib import Path\nfrom datetime import date\n\n# Add parent dir to path\nparent_directory = Path(__file__).parent.parent.parent.resolve()\nsys.path.append(str(parent_directory))\n\nimport webvtt  # noqa\n\n# -- Project information\n\nproject = 'webvtt-py'\ncopyright = f'2016-{date.today().year}, {webvtt.__author__}'\nauthor = webvtt.__author__\n\nrelease = webvtt.__version__\nversion = webvtt.__version__\n\n# -- General configuration\n\nextensions = [\n    'sphinx.ext.duration',\n    'sphinx.ext.doctest',\n    'sphinx.ext.autodoc',\n    'sphinx.ext.autosummary',\n    'sphinx.ext.intersphinx',\n]\n\nintersphinx_mapping = {\n    'python': ('https://docs.python.org/3/', None),\n    'sphinx': ('https://www.sphinx-doc.org/en/master/', None),\n}\nintersphinx_disabled_domains = ['std']\n\ntemplates_path = ['_templates']\n\n# -- Options for HTML output\n\nhtml_theme = 'sphinx_rtd_theme'\n\n# -- Options for EPUB output\nepub_show_urls = 'footnote'"
  },
  {
    "path": "docs/source/history.rst",
    "content": ".. include:: ../../CHANGELOG.rst"
  },
  {
    "path": "docs/source/index.rst",
    "content": "webvtt-py\n=========\n\nContents:\n\n.. toctree::\n   :maxdepth: 2\n\n   quickstart\n   usage\n   package\n   history\n\nIndices and tables\n==================\n\n* :ref:`genindex`\n* :ref:`modindex`"
  },
  {
    "path": "docs/source/package.rst",
    "content": "webvtt-py package reference\n===========================\n\nwebvtt.webvtt\n-------------\n\n.. automodule:: webvtt.webvtt\n    :members:\n\nwebvtt.segmenter\n----------------\n\n.. automodule:: webvtt.segmenter\n    :members:\n\nwebvtt.cli\n----------\n\n.. automodule:: webvtt.cli\n    :members:\n\nwebvtt.generic\n--------------\n\n.. automodule:: webvtt.structures\n    :members:\n\nwebvtt.parsers\n--------------\n\n.. automodule:: webvtt.parsers\n    :members:\n    :show-inheritance:\n\nwebvtt.writers\n--------------\n\n.. automodule:: webvtt.writers\n    :members:\n    :show-inheritance:\n\nwebvtt.exceptions\n-----------------\n\n.. automodule:: webvtt.exceptions\n    :members:\n"
  },
  {
    "path": "docs/source/quickstart.rst",
    "content": "Quickstart\n==========\n\nInstallation\n------------\n\nYou can install ``webvtt-py`` with pip:\n\n::\n\n    $ pip install webvtt-py\n\nTo install with easy_install:\n\n::\n\n    $ easy_install webvtt-py\n\nRequirements\n------------\n\nThis module requires Python 3.7+.\n\n\nSource code\n-----------\n\nThis project is hosted on `GitHub`_.\n\n.. _`GitHub`: https://github.com/glut23/webvtt-py\n\nLicense\n-------\n\nLicensed under the MIT License.\n"
  },
  {
    "path": "docs/source/usage.rst",
    "content": "Usage\n=====\n\nReading WebVTT caption files\n----------------------------\n\n.. code-block:: python\n\n    import webvtt\n\n    # we can iterate over the captions\n    for caption in webvtt.read('captions.vtt'):\n        print(caption.start)  # start timestamp in text format\n        print(caption.end)  # end timestamp in text format\n        print(caption.text)  # caption text\n        print(caption.voice)  # voice span if present\n\n    # you can also iterate over the lines of a particular caption\n    for line in vtt[0].lines:\n        print(line)\n\n    # caption text is returned clean without class tags\n    # we can access the raw text of a caption with raw_text\n    >>> vtt[0].text\n    'This is a caption text'\n    >>> vtt[0].raw_text\n    'This is a <c.colorE5E5E5>caption</c> text'\n\n    # caption identifiers\n    >>> vtt[0].identifier\n    'chapter 1'\n\n\nReading WebVTT caption files from a file-like object\n----------------------------------------------------\n\n.. code-block:: python\n\n    import webvtt\n    import requests\n    from io import StringIO\n\n    payload = requests.get('http://subtitles.com/1234.vtt').text()\n    buffer = StringIO(payload)\n\n    for caption in webvtt.from_buffer(buffer):\n        print(caption.start)\n        print(caption.end)\n        print(caption.text)\n\n\nReading WebVTT caption files from a BytesIO object\n--------------------------------------------------\n\n.. code-block:: python\n\n    import webvtt\n    from io import BytesIO\n\n    with open('captions.vtt', 'rb') as f:\n        buffer = BytesIO(f.read())\n\n    for caption in webvtt.from_buffer(buffer):\n        print(caption.start)\n        print(caption.end)\n        print(caption.text)\n\n\nReading caption files in other formats from a BytesIO object\n------------------------------------------------------------\n\n.. code-block:: python\n\n    import webvtt\n    from io import BytesIO\n\n    with open('captions.srt', 'rb') as f:\n        buffer = BytesIO(f.read())\n\n    # formats supported: vtt, srt, sbv\n    for caption in webvtt.from_buffer(buffer, format='srt'):\n        print(caption.start)\n        print(caption.end)\n        print(caption.text)\n\nReading WebVTT captions from a string\n-------------------------------------\n\n.. code-block:: python\n\n    import webvtt\n    import textwrap\n\n    vtt = webvtt.from_string(textwrap.dedent(\"\"\"\n        WEBVTT\n\n        00:00:00.500 --> 00:00:07.000\n        Caption #1\n\n        00:00:07.000 --> 00:00:11.890\n        Caption #2 line 1\n        Caption #2 line 2\n\n        00:00:11.890 --> 00:00:16.320\n        Caption #3\n        \"\"\").strip()\n        )\n\n    for caption in vtt:\n        print(caption.start)\n        print(caption.end)\n        print(caption.text)\n\n\nIterate a slice of captions\n---------------------------\n\n.. code-block:: python\n\n    import webvtt\n\n    vtt = webvtt.read('captions.vtt')\n    for caption in vtt.iter_slice(start='00:00:11.000',\n                                  end='00:00:27.000'\n                                  )\n        print(caption.start)\n        print(caption.end)\n        print(caption.text)\n\n\nCreating captions\n-----------------\n\n.. code-block:: python\n\n    from webvtt import WebVTT, Caption\n\n    vtt = WebVTT()\n\n    # creating a caption with a list of lines\n    caption = Caption(\n        '00:00:00.500',\n        '00:00:07.000',\n        ['Caption line 1', 'Caption line 2']\n    )\n\n    # an identifier can be assigned\n    caption.identifier = 'chapter 1'\n\n    # adding a caption\n    vtt.captions.append(caption)\n\n    # creating another caption with a text\n    caption = Caption(\n        '00:00:07.000',\n        '00:00:11.890',\n        'Caption line 1\\nCaption line 2'\n    )\n\n    vtt.captions.append(caption)\n\n\nManipulating captions\n---------------------\n\n.. code-block:: python\n\n    import webvtt\n\n    vtt = webvtt.read('captions.vtt')\n\n    # update start timestamp\n    vtt[0].start = '00:00:01.250'\n\n    # update end timestamp\n    vtt[0].end = '00:00:03.890'\n\n    # update caption text\n    vtt[0].text = 'New caption text'\n\n    # delete a caption\n    del vtt.captions[2]\n\n\nSaving captions\n---------------\n\n.. code-block:: python\n\n    import webvtt\n\n    vtt = webvtt.read('captions.vtt')\n\n    # save to the same file\n    vtt.save()\n\n    # save to a different file\n    vtt.save('new_captions.vtt')\n\n    # you can save to a file path\n    vtt.save('other/folder/new_captions')\n\n    # if there is a filename present in the object we can target a folder\n    vtt.save('other/folder)\n\n    # write to an opened file\n    with open('other_captions.vtt', 'w') as f:\n        vtt.write(f)\n\n\nRetrieving WebVTT formatted captions\n------------------------------------\n\nWebVTT content can be retrieved without an output file:\n\n.. code-block:: python\n\n    import webvtt\n\n    vtt = webvtt.read('captions.vtt')\n\n    # print the content in WebVTT format\n    print(vtt.content)\n\n\nConverting captions\n-------------------\n\nYou can read captions from the following formats:\n\n* SubRip (.srt)\n* YouTube SBV (.sbv)\n\n.. code-block:: python\n\n    import webvtt\n\n    # read captions from SRT format\n    vtt = webvtt.from_srt('captions.srt')\n\n    # save the captions in WebVTT format\n    vtt.save()\n\n    # the conversion can be done chaining the method calls\n    webvtt.from_srt('captions.srt').save()\n\n    # the same for SBV format\n    vtt = webvtt.from_sbv('captions.sbv')\n\nConvert WebVTT captions to other formats:\n\n* SubRip (.srt)\n\n.. code-block:: python\n\n    import webvtt\n\n    # save in SRT format\n    vtt = webvtt.read('captions.vtt')\n    vtt.save_as_srt()\n\n    # write to an opened file in SRT format\n    with open('captions.srt', 'w') as f:\n        vtt.write(f, format='srt')\n\n\nWebVTT files with Byte Order Mark (BOM)\n---------------------------------------\n\nWhen the WebVTT file has BOM, saving it will keep the BOM:\n\n.. code-block:: python\n\n    import webvtt\n\n    vtt = webvtt.read('captions_with_bom.vtt')\n\n    # saved file keeps the BOM\n    vtt.save()\n\n\nAdd a BOM to a file without it:\n\n.. code-block:: python\n\n    import webvtt\n\n    vtt = webvtt.read('captions_without_bom.vtt',\n                      add_bom=True\n                      )\n\n    # saved file has BOM\n    vtt.save()\n\n\nRemove the BOM from a file:\n\n.. code-block:: python\n\n    import webvtt\n\n    vtt = webvtt.read('captions_with_bom.vtt')\n\n    # saved file does not have BOM\n    vtt.save(add_bom=False)\n\n\nSave file with a different encoding:\n\n.. code-block:: python\n\n    import webvtt\n\n    vtt = webvtt.read('captions.vtt')\n\n    vtt.save(encoding='utf-32-le')\n\n    # save in different encoding with BOM\n    vtt.save(encoding='utf-32-le',\n             add_bom=True\n             )\n\n\n\nWebVTT Styles\n-------------\n\n.. code-block:: python\n\n    import webvtt\n\n    vtt = webvtt.read('captions.vtt')\n\n    for style in vtt.styles:\n        print(style.text)\n\n        # retrieve list of lines\n        print(style.lines)\n\n\nAdding styles:\n\n.. code-block:: python\n\n    import webvtt\n\n    vtt = webvtt.read('captions.vtt')\n\n    vtt.styles.append(\n        webvtt.Style('::cue(b) {\\n  color: peachpuff;\\n}')\n        )\n    # list of lines is supported\n    vtt.styles.append(\n        webvtt.Style(['::cue(b) {',\n                      '  color: peachpuff;',\n                      '}'\n                      ])\n        )\n\n\nUpdating styles:\n\n.. code-block:: python\n\n    import webvtt\n\n    vtt = webvtt.read('captions.vtt')\n\n    vtt.styles[0].lines[1] = '  color: papayawhip;'\n\n\nWebVTT Comments\n---------------\n\nComments can be added or retrieved from different items:\n\n.. code-block:: python\n\n    import webvtt\n\n    vtt = webvtt.read('captions.vtt')\n\n    # comments from the top of the file\n    print(vtt.header_comments)\n\n    # comments from the bottom of the file\n    print(vtt.footer_comments)\n\n    # comments in a style\n    print(vtt.styles[0].comments)\n\n    # comments in a caption\n    print(vtt.captions[0].comments)\n\n    # comments are just a list of strings\n    vtt.captions[5].comments.append('caption for review')\n\n"
  },
  {
    "path": "setup.cfg",
    "content": "[metadata]\ndescription_file = README.rst\n\n[flake8]\ndoctests = true\nradon-max-cc=10\n\n[tox:tox]\nenvlist =\n    codestyle\n    py\n    coverage\nisolated_build = True\n\n[coverage:run]\nsource = webvtt\nbranch = true\n\n[coverage:report]\nfail_under = 100\n\n[testenv]\ndeps =\n    coverage\ndescription = run the tests and provide coverage metrics\ncommands =\n    coverage run -m unittest discover\n\n[testenv:codestyle]\ndeps =\n    flake8\n    flake8-docstrings\n    radon\n    mypy\ncommands =\n    flake8 webvtt setup.py\n    mypy webvtt\n\n[testenv:coverage]\ndeps = coverage\ncommands =\n    coverage xml\n    coverage report\n"
  },
  {
    "path": "setup.py",
    "content": "\"\"\"webvtt-py setuptools configuration.\"\"\"\n\nimport re\nimport pathlib\n\nfrom setuptools import setup, find_packages\n\nversion, author, author_email = (\n    re.search(\n        rf'__{name}__ = \\'(.*?)\\'',\n        pathlib.Path('webvtt/__init__.py').read_text()\n        ).group(1)\n    for name in ('version', 'author', 'author_email')\n    )\n\nsetup(\n    name='webvtt-py',\n    version=version,\n    description='WebVTT reader, writer and segmenter',\n    long_description=pathlib.Path('README.rst').read_text(),\n    long_description_content_type='text/x-rst',\n    author=author,\n    author_email=author_email,\n    url='https://github.com/glut23/webvtt-py',\n    packages=find_packages('.', exclude=['tests']),\n    include_package_data=True,\n    entry_points={\n        'console_scripts': [\n            'webvtt=webvtt.cli:main'\n        ]\n    },\n    license='MIT',\n    python_requires='>=3.7',\n    classifiers=[\n        'Development Status :: 4 - Beta',\n        'Intended Audience :: Developers',\n        'License :: OSI Approved :: MIT License',\n        'Programming Language :: Python',\n        'Programming Language :: Python :: 3',\n        'Programming Language :: Python :: 3.7',\n        'Programming Language :: Python :: 3.8',\n        'Programming Language :: Python :: 3.9',\n        'Programming Language :: Python :: 3.10',\n        'Programming Language :: Python :: 3.11',\n        'Programming Language :: Python :: 3.12',\n        'Operating System :: OS Independent',\n        'Topic :: Software Development :: Libraries :: Python Modules',\n    ],\n    keywords='webvtt captions',\n)\n"
  },
  {
    "path": "tests/__init__.py",
    "content": ""
  },
  {
    "path": "tests/samples/captions_with_bom.vtt",
    "content": "﻿WEBVTT\n\n00:00:00.500 --> 00:00:07.000\nCaption text #1\n\n00:00:07.000 --> 00:00:11.890\nCaption text #2\n\n00:00:11.890 --> 00:00:16.320\nCaption text #3\n\n00:00:16.320 --> 00:00:21.580\nCaption text #4"
  },
  {
    "path": "tests/samples/comments.vtt",
    "content": "WEBVTT - Translation of that film I like\n\nNOTE\nThis translation was done by Kyle so that\nsome friends can watch it with their parents.\n\n1\n00:02:15.000 --> 00:02:20.000\n- Ta en kopp varmt te.\n- Det är inte varmt.\n\n2\n00:02:20.000 --> 00:02:25.000\n- Har en kopp te.\n- Det smakar som te.  \n\nNOTE This last line may not translate well.\n\n3\n00:02:25.000 --> 00:02:30.000\n- Ta en kopp\n\nNOTE end of file"
  },
  {
    "path": "tests/samples/cue_tags.vtt",
    "content": "WEBVTT\n\n00:16.500 --> 00:18.500\nWhen the moon <00:17.500>hits your eye\n\n00:00:18.500 --> 00:00:20.500\nLike a <00:19.000>big-a <00:19.500>pizza <00:20.000>pie\n\n00:00:20.500 --> 00:00:21.500\nThat's <00:00:21.000><c.colorE5E5E5>amore</c>"
  },
  {
    "path": "tests/samples/empty.vtt",
    "content": ""
  },
  {
    "path": "tests/samples/invalid.vtt",
    "content": "00:00:00.500 --> 00:00:07.000\nCaption text #1\n\n00:00:07.000 --> 00:00:11.890\nCaption text #2\n\n00:00:11.890 --> 00:00:16.320\nCaption text #3\n\n00:00:16.320 --> 00:00:21.580\nCaption text #4\n\n00:00:21.580 --> 00:00:23.880\nCaption text #5\n\n00:00:23.880 --> 00:00:27.280\nCaption text #6\n\n00:00:27.280 --> 00:00:30.280\nCaption text #7"
  },
  {
    "path": "tests/samples/invalid_format.sbv",
    "content": "some text"
  },
  {
    "path": "tests/samples/invalid_format1.srt",
    "content": "1"
  },
  {
    "path": "tests/samples/invalid_format2.srt",
    "content": "some text"
  },
  {
    "path": "tests/samples/invalid_format3.srt",
    "content": "1\nsome text"
  },
  {
    "path": "tests/samples/invalid_format4.srt",
    "content": "some text\n00:00:00,500 --> 00:00:07,000"
  },
  {
    "path": "tests/samples/invalid_timeframe.sbv",
    "content": "0:00:00.378,0:00:11.378\nCaption text #1\n\n0:00:11.378,0:00:12.305\nCaption text #2\n\n0:00:13.f89,0:00:15.489\nCaption text #3\n\n0:00:15.489,0:00:16.234\nCaption text #4\n\n0:00:17.484,0:00:16.543\nCaption text #5"
  },
  {
    "path": "tests/samples/invalid_timeframe.srt",
    "content": "1\n00:00:00,500 --> 00:00:07,000\nCaption text #1\n\n2\n00:00:07,000 --> 00:00:11.890\nCaption text #2\n\n3\n00:00:11,890 --> 00:00:16,320\nCaption text #3\n\n4\n00:00:16,320 --> 00:00:21,580\nCaption text #4\n\n5\n00:00:21,580 --> 00:00:23,880\nCaption text #5"
  },
  {
    "path": "tests/samples/invalid_timeframe.vtt",
    "content": "WEBVTT\n\n00:00:00.500 --> 00:00:07.000\nCaption text #1\n\n00:00:07.000 --> 00:00:1d.890\nCaption text #2\n\n00:00:11.890 --> 00:00:16.320\nCaption text #3\n\n00:00:16.320 --> 00:00:21.580\nCaption text #4\n\n00:00:21.580 --> 00:00:23.880\nCaption text #5\n\n00:00:23.880 --> 00:00:27.280\nCaption text #6\n\n00:00:27.280 --> 00:00:30.280\nCaption text #7"
  },
  {
    "path": "tests/samples/invalid_timeframe_in_cue_text.vtt",
    "content": "WEBVTT\n\n00:00:00.500 --> 00:00:07.000\nCaption text #1\n\n00:00:07.000 --> 00:00:10.890\n00:00:07.000 --> 00:00:10.890\nCaption text #2\n\n00:00:11.890 --> 00:00:16.320\nCaption text #3"
  },
  {
    "path": "tests/samples/metadata_headers.vtt",
    "content": "WEBVTT\nKind: captions\nLanguage: en\n\n00:00:00.500 --> 00:00:07.000\nCaption text #1\n\n00:00:07.000 --> 00:00:11.890\nCaption text #2"
  },
  {
    "path": "tests/samples/metadata_headers_multiline.vtt",
    "content": "WEBVTT\nKind: captions\nLanguage: en\nStyle:\n::cue(c.colorCCCCCC) { color: rgb(204, 204, 204);\n}\n##\n\n00:00:00.500 --> 00:00:07.000\nCaption text #1\n\n00:00:07.000 --> 00:00:11.890\nCaption text #2"
  },
  {
    "path": "tests/samples/missing_caption_text.sbv",
    "content": "0:00:00.378,0:00:11.378\nCaption text #1\n\n0:00:11.378,0:00:12.305\n\n0:00:13.489,0:00:15.489\nCaption text #3\n\n0:00:15.489,0:00:16.234\nCaption text #4\n\n0:00:17.484,0:00:16.543\nCaption text #5"
  },
  {
    "path": "tests/samples/missing_caption_text.srt",
    "content": "1\n00:00:00,500 --> 00:00:07,000\nCaption text #1\n\n2\n00:00:07,000 --> 00:00:11,890\n\n\n3\n00:00:11,890 --> 00:00:16,320\nCaption text #3\n\n4\n00:00:16,320 --> 00:00:21,580\nCaption text #4\n\n5\n00:00:21,580 --> 00:00:23,880\nCaption text #5"
  },
  {
    "path": "tests/samples/missing_caption_text.vtt",
    "content": "WEBVTT\n\n00:00:00.500 --> 00:00:07.000\nCaption text #1\n\n00:00:07.000 --> 00:00:11.890\n\n00:00:11.890 --> 00:00:16.320\nCaption text #3\n\n00:00:16.320 --> 00:00:21.580\nCaption text #4\n\n00:00:21.580 --> 00:00:23.880\nCaption text #5"
  },
  {
    "path": "tests/samples/missing_timeframe.sbv",
    "content": "0:00:00.378,0:00:11.378\nCaption text #1\n\nCaption text #2\n\n0:00:13.489,0:00:15.489\nCaption text #3\n\n0:00:15.489,0:00:16.234\nCaption text #4\n\n0:00:17.484,0:00:16.543\nCaption text #5"
  },
  {
    "path": "tests/samples/missing_timeframe.srt",
    "content": "1\n00:00:00,500 --> 00:00:07,000\nCaption text #1\n\n2\nCaption text #2\n\n3\n00:00:11,890 --> 00:00:16,320\nCaption text #3\n\n4\n00:00:16,320 --> 00:00:21,580\nCaption text #4\n\n5\n00:00:21,580 --> 00:00:23,880\nCaption text #5"
  },
  {
    "path": "tests/samples/missing_timeframe.vtt",
    "content": "WEBVTT\n\n00:00:00.500 --> 00:00:07.000\nCaption text #1\n\nCaption text #2\n\n00:00:11.890 --> 00:00:16.320\nCaption text #3\n\n00:00:16.320 --> 00:00:21.580\nCaption text #4\n\n00:00:21.580 --> 00:00:23.880\nCaption text #5\n\n00:00:23.880 --> 00:00:27.280\nCaption text #6\n\n00:00:27.280 --> 00:00:30.280\nCaption text #7"
  },
  {
    "path": "tests/samples/netflix_chicas_del_cable.vtt",
    "content": "WEBVTT\n\nNOTE Netflix\nNOTE Profile: webvtt-lssdh-ios8\nNOTE Date: 2017/04/16 15:44:03\n\nNOTE SegmentIndex\nNOTE Segment=597.080 20887@419 153\nNOTE Segment=592.000 23822@21306 173\nNOTE Segment=572.880 25784@45128 183\nNOTE Segment=575.160 18267@70912 131\nNOTE Segment=591.040 26386@89179 191\nNOTE Segment=220.440 4676@115565 34\nNOTE /SegmentIndex\n\n                                                   \n\n                    \n1\n00:00:07.960 --> 00:00:09.480  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[Alba] <i>En 1928,</i>\n\n2\n00:00:09.640 --> 00:00:13.080  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n<i>las mujeres éramos</i>\n<i>algo así como adornos</i>\n\n3\n00:00:13.240 --> 00:00:16.440  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n<i>que se llevaban a las fiestas</i>\n<i>para presumir de ellos.</i>\n\n4\n00:00:19.720 --> 00:00:22.160  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>Objetos sin poder de opinión ni decisión.</i>\n\n5\n00:00:22.640 --> 00:00:24.760  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>Es cierto que la vida no era fácil</i>\n\n6\n00:00:24.920 --> 00:00:27.680  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n<i>para nadie,</i>\n<i>pero mucho menos si eras mujer.</i>\n\n7\n00:00:29.320 --> 00:00:32.200  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>Si eras mujer, en 1928</i>\n\n8\n00:00:32.360 --> 00:00:35.160  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n<i>ser libre era</i>\n<i>algo que parecía inalcanzable.</i>\n\n9\n00:00:35.320 --> 00:00:36.880  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>Porque para la sociedad</i>\n\n10\n00:00:37.040 --> 00:00:41.040  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n<i>las mujeres solo éramos</i>\n<i>amas de casa, madres, esposas...</i>\n\n11\n00:00:42.000 --> 00:00:45.080  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n<i>No teníamos derecho</i>\n<i>a tener sueños ni ambiciones.</i>\n\n12\n00:00:45.240 --> 00:00:49.800  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n<i>Para buscar un futuro</i>\n<i>muchas tenían que marcharse lejos.</i>\n\n13\n00:00:49.960 --> 00:00:51.240  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nEn el bar de enfrente.\n\n14\n00:00:52.360 --> 00:00:53.400  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nTú no vas a ir\n\n15\n00:00:53.560 --> 00:00:54.600  position:50.00%,middle  align:middle size:80.00%  line:84.67% \na ningún sitio.\n\n16\n00:00:54.760 --> 00:00:56.480  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>Y otras tenían que enfrentarse</i>\n\n17\n00:00:56.640 --> 00:00:59.480  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n<i>a las normas de una sociedad</i>\n<i>machista y retrógrada.</i>\n\n18\n00:00:59.640 --> 00:01:02.000  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- Déjala.\n- Tú no te metas. ¡No te metas!\n\n19\n00:01:02.160 --> 00:01:06.600  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n<i>Al final, todas,</i>\n<i>ricas, pobres, queríamos lo mismo:</i>\n\n20\n00:01:06.760 --> 00:01:09.160  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>ser libres. Y si para eso</i>\n\n21\n00:01:09.320 --> 00:01:11.960  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n<i>había que quebrantar la ley,</i>\n<i>estábamos dispuestas</i>\n\n22\n00:01:12.120 --> 00:01:15.560  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n<i>a hacerlo</i>\n<i>sin importarnos las consecuencias.</i>\n\n23\n00:01:21.960 --> 00:01:23.520  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>Solo las que luchan por ellos</i>\n\n24\n00:01:23.680 --> 00:01:25.680  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>consiguen sus sueños.</i>\n\n25\n00:01:36.560 --> 00:01:37.920  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>Eso creíamos.</i>\n\n26\n00:01:38.080 --> 00:01:39.840  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>Lo que no sabíamos era</i>\n\n27\n00:01:40.000 --> 00:01:42.440  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>que el destino nos tenía preparadas</i>\n\n28\n00:01:42.600 --> 00:01:44.040  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>muchas sorpresas.</i>\n\n29\n00:01:46.520 --> 00:01:47.600  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nVámonos.\n\n30\n00:01:47.760 --> 00:01:48.800  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nRápido.\n\n31\n00:01:50.040 --> 00:01:51.800  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nArgentina nos espera.\n\n32\n00:01:51.960 --> 00:01:54.120  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[ríen emocionadas]\n\n33\n00:01:54.280 --> 00:01:55.400  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¡Corre!\n\n34\n00:01:56.400 --> 00:01:59.800  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- Nunca has montado en barco.\n- Así que pensabais escaparos...\n\n35\n00:02:00.560 --> 00:02:03.560  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n¡Ni se te ocurra moverte!\nEsto es entre Gimena y yo.\n\n36\n00:02:03.720 --> 00:02:06.640  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- Mi amiga no quiere volver a verte.\n- Que me lo diga ella.\n\n37\n00:02:06.800 --> 00:02:08.800  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nComo grites, te juro que te mato.\n\n38\n00:02:08.960 --> 00:02:10.560  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nTranquilízate, por favor.\n\n39\n00:02:10.720 --> 00:02:13.840  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n[Pedro] Lo haré cuando le digas a tu amiga\nque te vienes conmigo.\n\n40\n00:02:14.000 --> 00:02:15.880  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nNo se va a ir contigo.\n\n41\n00:02:16.040 --> 00:02:19.920  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nVa a hacer lo que yo diga. Si no,\nprimero la mato a ella y luego a ti.\n\n42\n00:02:20.080 --> 00:02:23.040  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nEstá bien, haré lo que quieras,\npero baja el arma.\n\n43\n00:02:23.200 --> 00:02:24.480  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¿Sí?\n\n44\n00:02:29.520 --> 00:02:31.040  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[grita con rabia]\n\n45\n00:02:31.200 --> 00:02:32.360  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[dos disparos]\n\n46\n00:02:32.520 --> 00:02:33.720  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¡Ah!\n\n47\n00:02:37.880 --> 00:02:39.920  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[respiración jadeante]\n\n48\n00:02:41.920 --> 00:02:45.560  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[respira agitada]\n\n49\n00:02:51.040 --> 00:02:52.240  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nGimena...\n\n50\n00:02:52.400 --> 00:02:53.840  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nGimena, no, por favor.\n\n51\n00:02:54.560 --> 00:02:58.240  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nMírame. Tú no tenías que estar aquí.\n\n52\n00:02:58.400 --> 00:03:00.360  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- No debería haberte traído.\n- Chist.\n\n53\n00:03:00.520 --> 00:03:02.760  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- Lo siento, lo siento.\n- Era nuestro sueño.\n\n54\n00:03:02.920 --> 00:03:04.680  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nEs, es nuestro sueño.\n\n55\n00:03:05.520 --> 00:03:07.000  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nLo sigue siendo.\n\n56\n00:03:07.160 --> 00:03:08.920  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- Mujeres libres...\n- Sí, sí.\n\n57\n00:03:11.640 --> 00:03:13.640  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[llora]\n\n58\n00:03:22.520 --> 00:03:24.520  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[truenos]\n\n59\n00:03:41.760 --> 00:03:45.000  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n[Beltrán] Así que estabas\nen la calle con dos cadáveres,\n\n60\n00:03:45.160 --> 00:03:47.160  position:50.00%,middle  align:middle size:80.00%  line:84.67% \npero no tienes nada que ver.\n\n61\n00:03:50.760 --> 00:03:52.640  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¿Y por qué debería creerte?\n\n62\n00:03:52.800 --> 00:03:55.480  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- Porque digo la verdad.\n- Alba Romero,\n\n63\n00:03:55.640 --> 00:03:59.280  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n25 años,\nantecedentes de hurto y estafa.\n\n64\n00:03:59.440 --> 00:04:01.480  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nY ahora además asesinato...\n\n65\n00:04:02.280 --> 00:04:05.080  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n¿Sabes lo que les pasa\na los acusados de asesinato?\n\n66\n00:04:05.640 --> 00:04:07.040  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nEl garrote vil.\n\n67\n00:04:07.200 --> 00:04:08.440  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[solloza]\n\n68\n00:04:08.600 --> 00:04:11.200  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nA no ser\nque colaboren con la justicia...\n\n69\n00:04:19.000 --> 00:04:20.279  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¿Cómo?\n\n70\n00:04:20.440 --> 00:04:23.280  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nPues haciendo\nlo que mejor sabes hacer.\n\n71\n00:04:24.840 --> 00:04:25.920  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nRobar.\n\n72\n00:04:27.280 --> 00:04:28.760  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nPero ahora para mí.\n\n73\n00:04:29.400 --> 00:04:30.680  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¿Qué me dices?\n\n74\n00:04:34.520 --> 00:04:36.520  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[tema musical]\n\n75\n00:05:34.600 --> 00:05:38.320  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n[Alba] <i>Y allí estaba: el nuevo rascacielos</i>\n<i>de la única compañía</i>\n\n76\n00:05:38.480 --> 00:05:40.120  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>de telefonía del país.</i>\n\n77\n00:05:41.080 --> 00:05:44.080  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n<i>13 plantas, más de 30 millones</i>\n<i>de metros de cable,</i>\n\n78\n00:05:44.240 --> 00:05:45.680  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>miles de trabajadores:</i>\n\n79\n00:05:45.840 --> 00:05:50.840  position:50.00%,middle  align:middle size:80.00%  line:10.00% \n<i>ejecutivos, telefonistas,</i>\n<i>800 puestos de trabajo libres</i>\n\n80\n00:05:51.000 --> 00:05:52.400  position:50.00%,middle  align:middle size:80.00%  line:10.00% \n<i>y una caja fuerte</i>\n\n81\n00:05:52.560 --> 00:05:54.920  position:50.00%,middle  align:middle size:80.00%  line:10.00% \n<i>llena de dinero que robar.</i>\n\n82\n00:05:55.080 --> 00:05:56.720  position:50.00%,middle  align:middle size:80.00%  line:10.00% \n[Sara] Por favor, señoritas...\n\n83\n00:05:57.560 --> 00:05:59.840  position:50.00%,middle  align:middle size:80.00%  line:10.00% \nBienvenidas a la nueva sede central\n\n84\n00:06:00.000 --> 00:06:01.640  position:50.00%,middle  align:middle size:80.00%  line:10.00% \nde la Compañía de Telefonía.\n\n85\n00:06:01.800 --> 00:06:05.400  position:50.00%,middle  align:middle size:80.00%  line:10.00% \nDisculpen tanto ir y venir,\naún estamos ultimando la mudanza.\n\n86\n00:06:05.560 --> 00:06:08.520  position:50.00%,middle  align:middle size:80.00%  line:10.00% \nDesde hoy, muchos de los servicios\nde la compañía\n\n87\n00:06:08.680 --> 00:06:11.800  position:50.00%,middle  align:middle size:80.00%  line:10.00% \ny las conexiones telefónicas\nse han centralizado aquí,\n\n88\n00:06:11.960 --> 00:06:14.240  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nasí que les pediría que presten atención.\n\n89\n00:06:14.400 --> 00:06:16.960  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nLas candidatas\npara los puestos a telefonistas,\n\n90\n00:06:17.120 --> 00:06:18.400  position:50.00%,middle  align:middle size:80.00%  line:84.67% \na la izquierda, en fila,\n\n91\n00:06:18.560 --> 00:06:20.760  position:50.00%,middle  align:middle size:80.00%  line:84.67% \ny vayan diciéndome sus nombres.\n\n92\n00:06:20.920 --> 00:06:24.120  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nBienvenida a la Compañía\nde Telefonía, ¿puedo ayudarla?\n\n93\n00:06:24.280 --> 00:06:27.400  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- Buenas, vengo para las pruebas...\n- De telefonista supongo.\n\n94\n00:06:27.560 --> 00:06:29.200  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- Sí.\n- Si me dice su nombre, la busco.\n\n95\n00:06:29.360 --> 00:06:30.360  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- Lidia.\n- Lidia...\n\n96\n00:06:30.520 --> 00:06:32.200  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- Lidia Aguilar.\n- Aguilar.\n\n97\n00:06:32.360 --> 00:06:35.800  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nPues lo lamento, no se encuentra\nentre las preseleccionadas.\n\n98\n00:06:35.960 --> 00:06:39.240  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n¿Preseleccionadas?\nPensaba que con presentarnos hoy...\n\n99\n00:06:39.400 --> 00:06:41.920  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nNo es la única,\nha habido un aluvión de solicitudes\n\n100\n00:06:42.080 --> 00:06:44.120  position:50.00%,middle  align:middle size:80.00%  line:84.67% \ny ha habido que hacer una preselección.\n\n101\n00:06:44.280 --> 00:06:45.880  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nLo siento muchísimo, Lidia.\n\n102\n00:06:46.040 --> 00:06:47.760  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- Gracias por venir.\n- Vaya...\n\n103\n00:06:47.920 --> 00:06:51.480  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- ¿Su nombre es?\n- Lidia Aguilar.\n\n104\n00:06:54.720 --> 00:06:56.760  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nLas pruebas\ndarán comienzo a las 12 en punto.\n\n105\n00:06:56.920 --> 00:06:59.840  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nQuien no esté dentro de la sala\nno podrá acceder a las pruebas.\n\n106\n00:07:00.000 --> 00:07:02.120  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nHay 390 solicitudes para 12 plazas.\n\n107\n00:07:02.280 --> 00:07:04.640  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n12 afortunadas que, les puedo asegurar,\n\n108\n00:07:04.800 --> 00:07:07.240  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nconseguirán el mejor trabajo de sus vidas,\n\n109\n00:07:07.400 --> 00:07:08.760  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nasí que no se despisten.\n\n110\n00:07:08.920 --> 00:07:10.440  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nAcompáñenme, por favor.\n\n111\n00:07:11.400 --> 00:07:12.640  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nEstán ustedes\n\n112\n00:07:12.800 --> 00:07:14.920  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nen el edificio más moderno de Madrid.\n\n113\n00:07:15.080 --> 00:07:17.920  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n13 plantas dedicadas\na la compañía de teléfonos.\n\n114\n00:07:18.080 --> 00:07:20.960  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nEn la planta uno podrán encontrar\nel Servicio de Atención al Público\n\n115\n00:07:21.120 --> 00:07:22.800  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>y el Departamento Comercial.</i>\n\n116\n00:07:22.960 --> 00:07:26.920  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n<i>En las plantas cuatro y cinco,</i>\n<i>los servicios administrativos.</i>\n\n117\n00:07:27.080 --> 00:07:28.520  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>En los pisos seis y siete,</i>\n\n118\n00:07:28.680 --> 00:07:31.120  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n<i>las centralitas,</i>\n<i>donde las elegidas tendrán</i>\n\n119\n00:07:31.280 --> 00:07:34.240  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n<i>el honor de trabajar.</i>\n<i>A continuación tenemos dos plantas</i>\n\n120\n00:07:34.400 --> 00:07:35.920  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>para las salas de máquinas,</i>\n\n121\n00:07:36.000 --> 00:07:38.040  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>Mantenimiento y despachos de Ingeniería.</i>\n\n122\n00:07:38.200 --> 00:07:41.960  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nMás arriba estarían las plantas\ndestinadas a eventos y reuniones.\n\n123\n00:07:42.120 --> 00:07:44.360  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nY, por último,\nen la planta 13 del edificio,\n\n124\n00:07:44.520 --> 00:07:46.120  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nlos despachos de Dirección.\n\n125\n00:08:00.040 --> 00:08:02.520  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- Gracias por todo.\n- Gracias, señor Cifuentes.\n\n126\n00:08:03.720 --> 00:08:04.920  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nEh, disculpe.\n\n127\n00:08:33.440 --> 00:08:34.840  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nSeñorita...\n\n128\n00:08:35.000 --> 00:08:37.080  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¿Puedo saber lo que está haciendo aquí?\n\n129\n00:08:37.679 --> 00:08:40.200  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n[cándida]\nVengo a las pruebas de telefonista\n\n130\n00:08:40.360 --> 00:08:41.960  position:50.00%,middle  align:middle size:80.00%  line:84.67% \ny me habían dicho que era aquí,\n\n131\n00:08:42.120 --> 00:08:44.360  position:50.00%,middle  align:middle size:80.00%  line:79.33% \npero es que no veo a nadie\npor ningún sitio.\n\n132\n00:08:45.000 --> 00:08:47.480  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n[risita] Sí. Son aquí si lleva\ntraje y chaqueta, es un hombre\n\n133\n00:08:47.560 --> 00:08:49.240  position:50.00%,middle  align:middle size:80.00%  line:84.67% \ny pretende ser ejecutivo de cuentas,\n\n134\n00:08:49.400 --> 00:08:51.120  position:50.00%,middle  align:middle size:80.00%  line:84.67% \ncosa que, por lo que veo, no es el caso.\n\n135\n00:08:51.280 --> 00:08:52.920  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nLas pruebas son en la sexta planta\n\n136\n00:08:53.080 --> 00:08:55.840  position:50.00%,middle  align:middle size:80.00%  line:79.33% \ny le quedan dos minutos\npara que le cierren las puertas,\n\n137\n00:08:56.000 --> 00:08:58.720  position:50.00%,middle  align:middle size:80.00%  line:79.33% \ny en esta empresa\nlo más importante es la puntualidad.\n\n138\n00:08:58.880 --> 00:08:59.920  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nMuchas gracias.\n\n139\n00:09:02.360 --> 00:09:04.400  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nMuy bien. ¿Ricardo Rodríguez?\n\n140\n00:09:05.680 --> 00:09:07.240  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nEh, bonita...\n\n141\n00:09:07.400 --> 00:09:08.920  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nPor la escalera mejor...\n\n142\n00:09:11.240 --> 00:09:12.240  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[risita]\n\n143\n00:09:24.320 --> 00:09:25.960  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[ambas gritan]\n\n144\n00:09:28.040 --> 00:09:30.400  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nAy, que nos han cerrado, estamos fuera.\n\n145\n00:09:30.560 --> 00:09:32.360  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nLas pruebas empezaban a las 12.\n\n146\n00:09:32.520 --> 00:09:33.800  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nEs que soy lo peor.\n\n147\n00:09:33.960 --> 00:09:36.920  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- Me perdí tres veces en el metro.\n- [Ángeles] No, no, no, no puede...\n\n148\n00:09:38.360 --> 00:09:40.200  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- ¿Sí?\n- Disculpe.\n\n149\n00:09:40.800 --> 00:09:43.120  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- Venimos a las pruebas.\n- Llegan tarde.\n\n150\n00:09:43.280 --> 00:09:46.680  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nLo sé. Sé que lo primero\nen esta empresa es la puntualidad.\n\n151\n00:09:46.840 --> 00:09:49.160  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nEntonces,\n¿para qué ha llamado a la puerta?\n\n152\n00:09:50.040 --> 00:09:52.320  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nPara saber si lo segundo\n\n153\n00:09:52.480 --> 00:09:53.600  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nes la comprensión.\n\n154\n00:09:57.080 --> 00:09:58.440  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¡Mírela!\n\n155\n00:09:58.880 --> 00:10:00.880  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nDirectamente desde la estación\n\n156\n00:10:01.040 --> 00:10:04.200  position:50.00%,middle  align:middle size:80.00%  line:79.33% \ncon la misma maleta,\n600 km para poder estar aquí ahora.\n\n157\n00:10:04.360 --> 00:10:05.800  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- 550.\n- Sí.\n\n158\n00:10:06.880 --> 00:10:10.320  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nY por solo un minuto va a volverse\na casa con las manos vacías.\n\n159\n00:10:11.880 --> 00:10:12.840  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nLa culpa ha sido mía.\n\n160\n00:10:13.760 --> 00:10:15.160  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nSeñorita Millán...\n\n161\n00:10:16.960 --> 00:10:18.480  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[tartamudea] Lo siento mucho.\n\n162\n00:10:19.440 --> 00:10:21.160  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nYo me he ofrecido a acompañarlas\n\n163\n00:10:21.320 --> 00:10:23.360  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nde paso que le traía la documentación\n\n164\n00:10:23.520 --> 00:10:25.960  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nque me pidió usted\ny me he confundido de piso.\n\n165\n00:10:26.120 --> 00:10:27.320  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nSe equivocó de piso...\n\n166\n00:10:27.480 --> 00:10:28.480  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nSí.\n\n167\n00:10:28.880 --> 00:10:31.640  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nSu primera equivocación\ndesde que trabaja para mí.\n\n168\n00:10:31.800 --> 00:10:34.280  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nNuestros trabajadores\nson sumamente comprensivos.\n\n169\n00:10:34.440 --> 00:10:37.000  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nAunque, para su desgracia,\nno depende de Ángeles\n\n170\n00:10:37.160 --> 00:10:39.360  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nque crucen o no esta puerta,\ndepende de mí.\n\n171\n00:10:49.040 --> 00:10:50.640  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- Gracias.\n- Sí, muchas gracias.\n\n172\n00:10:50.800 --> 00:10:53.040  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nSi me presento en el pueblo\nsin haber hecho...\n\n173\n00:10:53.200 --> 00:10:54.600  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- Ángeles, ¿verdad?\n- Ajá.\n\n174\n00:10:54.760 --> 00:10:57.880  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nCon ese nombre, solamente podías ser\nnuestro ángel de la guarda.\n\n175\n00:10:58.040 --> 00:10:59.640  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nYo no diría tanto...\n\n176\n00:11:01.680 --> 00:11:03.080  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nPerdón. Aquí.\n\n177\n00:11:04.680 --> 00:11:05.800  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nDisculpe.\n\n178\n00:11:07.000 --> 00:11:10.120  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nNo habría alguna posibilidad\nde pasar las pruebas\n\n179\n00:11:10.280 --> 00:11:12.040  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- sin hacerlas, ¿verdad?\n- No.\n\n180\n00:11:12.200 --> 00:11:13.240  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nBuenos días.\n\n181\n00:11:13.800 --> 00:11:15.280  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nSeñoritas...\n\n182\n00:11:19.240 --> 00:11:22.000  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nVeo que hoy va a ser\nun gran día para esta compañía.\n\n183\n00:11:22.480 --> 00:11:24.360  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¿Vienen todas a las pruebas?\n\n184\n00:11:25.320 --> 00:11:27.600  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nMe parece que va a ser muy difícil elegir.\n\n185\n00:11:28.320 --> 00:11:30.240  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nOjalá pudiéramos comprar más centralitas\n\n186\n00:11:30.400 --> 00:11:31.720  position:50.00%,middle  align:middle size:80.00%  line:84.67% \npara darles trabajo a todas.\n\n187\n00:11:31.800 --> 00:11:33.240  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n[Ángeles ríe]\n[lapicero cae]\n\n188\n00:11:39.040 --> 00:11:40.200  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nGracias.\n\n189\n00:11:40.360 --> 00:11:43.880  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nNo quiero ponerlas más nerviosas\nde lo que ya están, así que...\n\n190\n00:11:44.440 --> 00:11:47.360  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nles deseo mucha suerte\na cada una de ustedes.\n\n191\n00:11:48.280 --> 00:11:49.440  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[inaudible]\n\n192\n00:12:36.760 --> 00:12:39.440  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nRemedios Fuentes, admitida. Lucía Billar,\n\n193\n00:12:39.600 --> 00:12:41.800  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nno admitida. Marta Rodríguez, admitida.\n\n194\n00:12:41.960 --> 00:12:45.080  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nLaura Sarmiento, admitida.\nVerónica Sánchez, admitida.\n\n195\n00:12:45.240 --> 00:12:48.960  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nÁngeles Montes, no admitida.\nCarlota Rodríguez de Senillosa,\n\n196\n00:12:49.120 --> 00:12:51.760  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nadmitida. María José Pando, admitida.\n\n197\n00:12:51.920 --> 00:12:54.440  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nMaría Inmaculada Suárez, admitida.\n\n198\n00:12:55.840 --> 00:12:58.360  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nEnhorabuena a las elegidas.\n\n199\n00:12:59.680 --> 00:13:00.880  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nDisculpe.\n\n200\n00:13:01.280 --> 00:13:02.320  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nPerdón.\n\n201\n00:13:02.480 --> 00:13:05.840  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- No ha dicho mi nombre.\n- Eso es que no ha pasado las pruebas.\n\n202\n00:13:06.000 --> 00:13:07.520  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¿Cómo? Me gustaría ver el listado.\n\n203\n00:13:07.680 --> 00:13:11.160  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nLos resultados no son públicos,\npero le aseguro que sí son justos.\n\n204\n00:13:11.320 --> 00:13:13.600  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- Tengo derecho a saber...\n- No tiene derecho a nada.\n\n205\n00:13:13.760 --> 00:13:15.760  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nNo ha pasado las pruebas, punto y final.\n\n206\n00:13:15.920 --> 00:13:16.920  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[Carlos] ¿Va todo bien?\n\n207\n00:13:31.320 --> 00:13:33.840  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nSeñorita Aguilar,\n¿en qué academia ha estudiado?\n\n208\n00:13:34.000 --> 00:13:35.040  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nSoy autodidacta.\n\n209\n00:13:35.200 --> 00:13:36.360  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- ¿Autodidacta?\n- Sí.\n\n210\n00:13:36.520 --> 00:13:39.200  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n¿Usted nunca ha estudiado nada\npor su cuenta?\n\n211\n00:13:39.360 --> 00:13:42.000  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nYo, si le soy sincero, nunca he estudiado.\n\n212\n00:13:42.800 --> 00:13:44.960  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nPero no deje que se entere mi padre,\n\n213\n00:13:45.120 --> 00:13:46.440  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nno me gustaría que pensase\n\n214\n00:13:46.600 --> 00:13:49.240  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nque desperdició su dinero\npagándome un internado.\n\n215\n00:13:52.560 --> 00:13:53.640  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nMe imagino que no sabe\n\n216\n00:13:53.800 --> 00:13:56.160  position:50.00%,middle  align:middle size:80.00%  line:79.33% \npor qué, habiendo\nunas pruebas más que decentes,\n\n217\n00:13:56.320 --> 00:13:57.680  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nno está entre las elegidas.\n\n218\n00:13:57.840 --> 00:13:58.960  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nSus brazos...\n\n219\n00:14:00.600 --> 00:14:02.800  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- ¿Cómo?\n- No son lo suficientemente largos.\n\n220\n00:14:02.960 --> 00:14:05.000  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nMuchos abonados, paneles muy grandes...\n\n221\n00:14:05.160 --> 00:14:08.640  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nA veces una telefonista tiene que\nhacerse cargo de hasta dos paneles.\n\n222\n00:14:08.800 --> 00:14:10.200  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nCon su permiso...\n\n223\n00:14:11.960 --> 00:14:15.000  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nLe faltan dos centímetros\npara estar en el mínimo exigido.\n\n224\n00:14:15.760 --> 00:14:17.880  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nPerdone el atrevimiento, don Carlos,\n\n225\n00:14:18.040 --> 00:14:20.560  position:50.00%,middle  align:middle size:80.00%  line:79.33% \npero este requisito\nme parece una tontería.\n\n226\n00:14:20.720 --> 00:14:21.880  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¿Perdón?\n\n227\n00:14:22.040 --> 00:14:25.680  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nTrinidad Seijo, telefonista\nde la centralita de mi pueblo,\n\n228\n00:14:25.840 --> 00:14:28.920  position:50.00%,middle  align:middle size:80.00%  line:79.33% \ncontrolaba toda la comarca,\nmás de 300 abonados,\n\n229\n00:14:29.080 --> 00:14:32.080  position:50.00%,middle  align:middle size:80.00%  line:79.33% \ntodo lo hacía con una mano...\nporque era manca.\n\n230\n00:14:33.560 --> 00:14:36.080  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nAsí que no creo que sea\nuna cuestión de centímetros\n\n231\n00:14:36.240 --> 00:14:37.240  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nsino de habilidad.\n\n232\n00:14:40.040 --> 00:14:42.160  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nDígame por qué quiere ser telefonista.\n\n233\n00:14:42.320 --> 00:14:45.400  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nQuiere que le diga que es\nel mejor trabajo del mundo, ¿verdad?\n\n234\n00:14:45.560 --> 00:14:46.960  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nPero es que no puedo hacer eso\n\n235\n00:14:47.120 --> 00:14:49.560  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nporque entonces usted y yo\nsabríamos que miento.\n\n236\n00:14:50.720 --> 00:14:53.520  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nEl suyo es mucho mejor.\nPero, por desgracia,\n\n237\n00:14:53.680 --> 00:14:55.320  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nme han dicho que no está vacante.\n\n238\n00:14:55.480 --> 00:14:58.120  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nCon carácter, don de la palabra\ny sentido del humor.\n\n239\n00:14:58.280 --> 00:15:00.880  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nEstoy segura de que no es\nla primera que conoce así.\n\n240\n00:15:01.040 --> 00:15:02.520  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nHe conocido unas pocas, sí.\n\n241\n00:15:03.440 --> 00:15:05.200  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nAunque no sé si alguna como usted.\n\n242\n00:15:05.840 --> 00:15:07.240  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nNo, como yo no.\n\n243\n00:15:11.000 --> 00:15:13.400  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nCarolina, acompañe a la señorita abajo...\n\n244\n00:15:14.440 --> 00:15:17.120  position:50.00%,middle  align:middle size:80.00%  line:79.33% \ny confírmele a Sara\nque está entre las seleccionadas.\n\n245\n00:15:17.280 --> 00:15:19.000  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- Bienvenida, señorita Aguilar.\n- Gracias.\n\n246\n00:15:19.160 --> 00:15:21.560  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nLa próxima vez que quiera\nimpresionar a un directivo\n\n247\n00:15:21.720 --> 00:15:23.600  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nno le diga\nque sueña con quitarle el puesto.\n\n248\n00:15:23.760 --> 00:15:26.480  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nY usted la próxima vez\nque quiera impresionar a una mujer\n\n249\n00:15:26.640 --> 00:15:29.200  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nno le haga sentir\nque solo le interesan sus medidas.\n\n250\n00:15:32.920 --> 00:15:35.800  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nAl final te ha servido esa carita\nde no haber roto un plato.\n\n251\n00:15:36.400 --> 00:15:37.720  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¿Perdona?\n\n252\n00:15:37.880 --> 00:15:41.120  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- No sé de qué me estás hablando...\n- La actitud de mosquita muerta.\n\n253\n00:15:41.280 --> 00:15:44.040  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nTe servirá con Sara\ny con don Carlos, pero conmigo no.\n\n254\n00:15:44.200 --> 00:15:45.600  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nTe voy a estar vigilando.\n\n255\n00:15:49.680 --> 00:15:52.320  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nBonita, por la escalera mejor...\n\n256\n00:15:58.560 --> 00:15:59.720  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[ríe suavemente]\n\n257\n00:16:03.880 --> 00:16:05.960  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[señal de teléfono y voces]\n\n258\n00:16:06.120 --> 00:16:09.080  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n[Ángeles] Buenas tardes, operadora tres,\n¿en qué puedo ayudarle?\n\n259\n00:16:10.880 --> 00:16:12.320  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nUn momento, por favor.\n\n260\n00:16:12.480 --> 00:16:14.600  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nBuenos días, operadora número 20.\n\n261\n00:16:20.000 --> 00:16:23.960  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nAquí Central.\nTiene una llamada del abonado 235.\n\n262\n00:16:24.160 --> 00:16:25.520  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¿Desea aceptarla?\n\n263\n00:16:26.280 --> 00:16:27.520  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nGracias.\n\n264\n00:16:28.000 --> 00:16:30.200  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[Sara] Gracias, Ángeles, es suficiente.\n\n265\n00:16:30.360 --> 00:16:33.240  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nÁngeles es la que mejor\nconoce esta empresa y su trabajo.\n\n266\n00:16:33.400 --> 00:16:35.440  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[Alba] <i>La telefonista que mejor conocía</i>\n\n267\n00:16:35.600 --> 00:16:38.120  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n<i>esa empresa y su trabajo.</i>\n<i>Sin duda, si alguien</i>\n\n268\n00:16:38.280 --> 00:16:40.200  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>podía contarme todo lo que necesitaba</i>\n\n269\n00:16:40.360 --> 00:16:43.600  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n<i>para robar aquella caja fuerte</i>\n<i>y cumplir mi sueño era Ángeles.</i>\n\n270\n00:16:43.760 --> 00:16:45.280  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n...mañana, tarde y noche.\n\n271\n00:16:45.440 --> 00:16:48.280  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n<i>Solo tenía que acercarme a ella</i>\n<i>y conseguir que confiase</i>\n\n272\n00:16:48.440 --> 00:16:51.000  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n<i>lo suficiente en mí</i>\n<i>como para contarme los secretos</i>\n\n273\n00:16:51.160 --> 00:16:54.920  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- <i>de la Compañía de Telefonía</i>.\n- Cuando suena el gong, es el momento\n\n274\n00:16:55.080 --> 00:16:57.360  position:50.00%,middle  align:middle size:80.00%  line:79.33% \ndel cambio de puesto,\n¿está todo claro? Bien.\n\n275\n00:16:57.520 --> 00:16:58.800  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nAhora, si me disculpan,\n\n276\n00:16:58.960 --> 00:17:01.560  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nel director de la compañía\nquiere presentarse.\n\n277\n00:17:02.440 --> 00:17:05.680  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nDon Francisco, le presento\na las nuevas incorporaciones:\n\n278\n00:17:05.839 --> 00:17:06.880  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nMarta Rodríguez...\n\n279\n00:17:07.040 --> 00:17:10.400  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nEl dire... Pero ¿el director\nno era don Carlos Cifuentes?\n\n280\n00:17:10.560 --> 00:17:13.480  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- Es el hijo del dueño.\n- ¿Y quién es el director?\n\n281\n00:17:14.480 --> 00:17:15.960  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[Sara] Laura Sarmiento.\n\n282\n00:17:17.319 --> 00:17:18.720  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nPetra Silva.\n\n283\n00:17:19.480 --> 00:17:20.720  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nLourdes Trapero.\n\n284\n00:17:22.640 --> 00:17:24.400  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nElla es la señorita Raquel Levante.\n\n285\n00:17:24.960 --> 00:17:28.760  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nRemedios Fuentes.\nCarlota Rodríguez de Senillosa.\n\n286\n00:17:29.720 --> 00:17:31.200  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nLidia Aguilar.\n\n287\n00:17:32.080 --> 00:17:33.240  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nAlba.\n\n288\n00:17:34.920 --> 00:17:37.600  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nLo lamento, pero\nse ha equivocado de persona, no...\n\n289\n00:17:38.160 --> 00:17:39.960  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nMe llamo Lidia Aguilar.\n\n290\n00:17:40.120 --> 00:17:41.160  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nEncantada.\n\n291\n00:17:43.360 --> 00:17:45.000  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nLo siento, señorita Aguilar.\n\n292\n00:17:45.520 --> 00:17:47.400  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nMe ha recordado a una vieja amiga.\n\n293\n00:17:48.520 --> 00:17:49.960  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nNo se apure.\n\n294\n00:17:53.320 --> 00:17:54.600  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[Sara] María José Pando.\n\n295\n00:17:57.560 --> 00:17:59.960  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n[joven Francisco]\n<i>Corre, Alba, vamos, venga.</i>\n\n296\n00:18:00.120 --> 00:18:01.240  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¡Corre, corre, corre!\n\n297\n00:18:01.400 --> 00:18:03.320  position:50.00%,middle  align:middle size:80.00%  line:10.00% \nPasa, pásame la maleta.\n\n298\n00:18:03.480 --> 00:18:06.160  position:50.00%,middle  align:middle size:80.00%  line:10.00% \n[joven Alba] <i>Aún no me creo</i>\n<i>que nos vayamos a Madrid.</i>\n\n299\n00:18:06.320 --> 00:18:07.800  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¿Te estás arrepintiendo?\n\n300\n00:18:07.960 --> 00:18:09.000  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¿Tú estás loco?\n\n301\n00:18:09.440 --> 00:18:12.400  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nEstaba pensando en todas las cosas\nque haré cuando llegue,\n\n302\n00:18:12.560 --> 00:18:13.960  position:50.00%,middle  align:middle size:80.00%  line:84.67% \ncomo encontrar un trabajo.\n\n303\n00:18:14.120 --> 00:18:17.880  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nDespués ahorraré mucho, muchísimo\ny me compraré un vestido precioso.\n\n304\n00:18:18.040 --> 00:18:20.440  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nE iré a la verbena\ny me tomaré un <i>white lady</i>.\n\n305\n00:18:20.600 --> 00:18:21.760  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¿Un <i>white lady</i>?\n\n306\n00:18:21.920 --> 00:18:24.360  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nClaro. Es lo que toman\nlas chicas de ciudad.\n\n307\n00:18:25.880 --> 00:18:27.640  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- ¿Qué vas a hacer tú?\n- ¿Yo?\n\n308\n00:18:28.280 --> 00:18:31.320  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nVoy a besar este lunar tan bonito\nque tienes en el cuello.\n\n309\n00:18:44.200 --> 00:18:46.560  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¡Eh! ¡Mi maleta! ¡Oiga!\n\n310\n00:18:47.080 --> 00:18:48.240  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¡Oiga!\n\n311\n00:18:54.960 --> 00:18:58.480  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- Eh, eh, ladrón, que es mi maleta.\n- Oiga, no, es mi maleta. Oiga.\n\n312\n00:19:00.120 --> 00:19:02.320  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¡Suélteme! ¡Francisco!\n\n313\n00:19:02.480 --> 00:19:04.240  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>¡Francisco!</i>\n\n314\n00:19:12.280 --> 00:19:13.920  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[teléfono]\n\n315\n00:19:16.040 --> 00:19:18.240  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[teléfono]\n\n316\n00:19:20.360 --> 00:19:23.480  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- Te dije que no me llamaras aquí.\n- [Alba] <i>Es una emergencia, Beltrán.</i>\n\n317\n00:19:23.640 --> 00:19:24.880  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nHa surgido un problema.\n\n318\n00:19:25.040 --> 00:19:27.320  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nY no puedo dar\nel golpe que tenía previsto,\n\n319\n00:19:27.480 --> 00:19:29.920  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nnecesito buscar otro sitio...\ny más tiempo.\n\n320\n00:19:30.080 --> 00:19:34.400  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nNo me cuentes tu vida. ¿Sabes\ncuál es la condena por asesinato?\n\n321\n00:19:34.560 --> 00:19:35.640  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nLa muerte.\n\n322\n00:19:35.800 --> 00:19:37.960  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>Tienes un día para librarte de ella.</i>\n\n323\n00:19:38.120 --> 00:19:39.960  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>Mañana a la una en el parque.</i>\n\n324\n00:19:40.120 --> 00:19:41.600  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[Beltrán cuelga]\n\n325\n00:19:42.320 --> 00:19:45.560  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nCarlota...\n¿Entonces sabes cómo llegar aquí?\n\n326\n00:19:46.240 --> 00:19:48.920  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nPensión Dolores, calle Blancaró.\n\n327\n00:19:49.080 --> 00:19:52.440  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nSí, mujer, esto no tiene pérdida.\nMira, tienes que seguir todo recto\n\n328\n00:19:52.600 --> 00:19:54.600  position:50.00%,middle  align:middle size:80.00%  line:84.67% \ny luego giras la tercera a la izquierda.\n\n329\n00:19:54.760 --> 00:19:57.640  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- [hombre] Es la segunda a la izquierda.\n- ¿Y quién dice eso?\n\n330\n00:19:57.800 --> 00:19:59.200  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nMiguel Pascual.\n\n331\n00:20:00.040 --> 00:20:01.720  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nIngeniero de comunicaciones.\n\n332\n00:20:01.880 --> 00:20:05.080  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nMadrileño de cuna,\nun humilde conocedor de la villa.\n\n333\n00:20:05.320 --> 00:20:07.520  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n[ríe] ¿Has oído, Marga?\nUn hombre polifacético.\n\n334\n00:20:07.680 --> 00:20:09.760  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nMíralo, porque de esos quedan muy pocos.\n\n335\n00:20:09.920 --> 00:20:11.080  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nLe digo lo mismo...\n\n336\n00:20:11.240 --> 00:20:12.320  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¡Ah!\n\n337\n00:20:13.200 --> 00:20:14.440  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nÉl es Miguel.\n\n338\n00:20:14.600 --> 00:20:16.720  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[azorada] Ah, pero que es tu novio...\n\n339\n00:20:16.880 --> 00:20:20.040  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nNo repitas esa palabra\ndelante de ella, es alérgica.\n\n340\n00:20:20.200 --> 00:20:23.400  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nOye, luego voy a tomarme algo\nal bar de enfrente, ¿te apuntas?\n\n341\n00:20:23.560 --> 00:20:24.920  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nCierro unas cosas y te busco.\n\n342\n00:20:26.480 --> 00:20:30.360  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nLidia, ¿te vienes al bar de enfrente\na tomar algo con nosotras?\n\n343\n00:20:30.520 --> 00:20:32.280  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nNo, tengo cosas que hacer.\n\n344\n00:20:32.440 --> 00:20:33.480  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[Marga] ¿Yo puedo ir?\n\n345\n00:20:33.640 --> 00:20:36.760  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nAunque sea a agradecerle a Ángeles\ntodo lo que ha hecho por nosotras.\n\n346\n00:20:36.920 --> 00:20:38.880  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- ¿Ángeles va?\n- Sí.\n\n347\n00:20:39.040 --> 00:20:41.840  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nVa a dejar al niño con la vecina\nporque no quería demorarse mucho.\n\n348\n00:20:42.000 --> 00:20:43.720  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- Bueno, ¿qué, te vienes?\n- [Ángeles] Hola.\n\n349\n00:20:45.320 --> 00:20:47.880  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nLa familia Cifuentes ha hecho\nuna inversión muy grande\n\n350\n00:20:48.040 --> 00:20:49.600  position:50.00%,middle  align:middle size:80.00%  line:84.67% \ncon la construcción del edificio.\n\n351\n00:20:49.760 --> 00:20:52.080  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nAhora es lógico\nque quieran aumentar la seguridad.\n\n352\n00:20:52.240 --> 00:20:54.440  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nY solo se puede acceder\ndurante nuestro turno...\n\n353\n00:20:54.600 --> 00:20:56.200  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nClaro, tienen que ser precavidos.\n\n354\n00:20:56.360 --> 00:20:59.840  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nTodo pasa por la central:\nrecaudación de la empresa, el sueldo\n\n355\n00:21:00.000 --> 00:21:01.720  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nde los empleados... Básicamente todo.\n\n356\n00:21:01.880 --> 00:21:03.760  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[Marga] Abuela, que me va a dejar sorda.\n\n357\n00:21:03.920 --> 00:21:06.400  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¿Ves? Si es que vales más que las pesetas.\n\n358\n00:21:06.560 --> 00:21:08.320  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>Verás cuando se lo diga a la Rosario.</i>\n\n359\n00:21:08.480 --> 00:21:11.040  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nNo, abuela,\nantes de que le diga nada a nadie...\n\n360\n00:21:11.840 --> 00:21:15.040  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nQue, a ver, abuela,\nque yo lo he estado pensando y...\n\n361\n00:21:15.840 --> 00:21:17.360  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nY lo mejor es que renuncie.\n\n362\n00:21:17.520 --> 00:21:21.160  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- <i>Que me vuelva al pueblo con usted.</i>\n- ¿Cómo? Pero ¿estás loca?\n\n363\n00:21:21.720 --> 00:21:23.320  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nNo somos una familia de posibles\n\n364\n00:21:23.480 --> 00:21:25.760  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nni tienes un marido\nque te resuelva la vida.\n\n365\n00:21:25.920 --> 00:21:28.520  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n<i>No voy a dejar que te quedes</i>\n<i>el resto de tu vida en el pueblo</i>\n\n366\n00:21:28.680 --> 00:21:29.960  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>cuidando de una vieja, no.</i>\n\n367\n00:21:30.120 --> 00:21:31.720  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>Ya te has sacrificado suficiente</i>\n\n368\n00:21:31.880 --> 00:21:34.360  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n<i>por tu madre, que en paz descanse,</i>\n<i>todos estos años.</i>\n\n369\n00:21:34.520 --> 00:21:35.880  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nYa, abuela, pero...\n\n370\n00:21:36.280 --> 00:21:39.680  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nPero es que yo he sido muy feliz\ncon usted y con madre.\n\n371\n00:21:39.840 --> 00:21:43.440  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nY ella contigo, hija, pero ahora\ntienes que ocuparte de ti misma.\n\n372\n00:21:43.600 --> 00:21:46.560  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n<i>Y por una vez en tu vida</i>\n<i>pensar solo en ti, no en los demás.</i>\n\n373\n00:21:46.720 --> 00:21:49.560  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nYa, abuela, ya lo sé,\ny es lo que hago, pero...\n\n374\n00:21:51.240 --> 00:21:53.520  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nPero es que la capital\nme queda muy grande.\n\n375\n00:21:53.680 --> 00:21:55.360  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nEl miedo se pasa, Marga.\n\n376\n00:21:56.920 --> 00:21:59.440  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nY la vida también, si no se aprovecha.\n\n377\n00:21:59.600 --> 00:22:00.760  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>No lo olvides.</i>\n\n378\n00:22:00.920 --> 00:22:01.920  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nGracias.\n\n379\n00:22:02.760 --> 00:22:06.000  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nAbuela, que...\nQue la tengo que dejar, ¿vale?\n\n380\n00:22:06.440 --> 00:22:08.840  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nCuídese mucho. [beso] La quiero.\n\n381\n00:22:14.880 --> 00:22:16.000  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nEs mucho dinero...\n\n382\n00:22:16.160 --> 00:22:18.880  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n[Carlota] Bueno, vamos a dejar\nde hablar de trabajo y vamos a brindar.\n\n383\n00:22:19.040 --> 00:22:20.120  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nLos vermús.\n\n384\n00:22:20.280 --> 00:22:22.120  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nPero el vermú lleva alcohol.\n\n385\n00:22:23.080 --> 00:22:26.120  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nSí, sí, sí, pero puedes tomar\notra cosa, si prefieres.\n\n386\n00:22:27.680 --> 00:22:29.400  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nNo, no, esto está bien.\n\n387\n00:22:30.120 --> 00:22:32.520  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nBueno, a lo mejor\npara mí es muy fuerte.\n\n388\n00:22:32.680 --> 00:22:35.320  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nYo hace que no me tomo uno...\nNi me acuerdo.\n\n389\n00:22:35.480 --> 00:22:37.600  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nNo entraba a un bar\ndesde que me quedé embarazada.\n\n390\n00:22:37.760 --> 00:22:39.200  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nAsí te preparas para el champán\n\n391\n00:22:39.360 --> 00:22:41.160  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- de la fiesta de esta noche.\n- [Marga] ¿Qué fiesta?\n\n392\n00:22:41.320 --> 00:22:43.280  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n[Carlota] ¿Cómo que qué fiesta?\nLa de inauguración.\n\n393\n00:22:43.440 --> 00:22:44.400  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[Ángeles] Va todo el mundo.\n\n394\n00:22:44.560 --> 00:22:46.880  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nYo no puedo porque me tengo\nque quedar con mi hija,\n\n395\n00:22:47.040 --> 00:22:49.880  position:50.00%,middle  align:middle size:80.00%  line:79.33% \npero van telefonistas,\noficinistas, van hasta los jefes.\n\n396\n00:22:50.040 --> 00:22:52.560  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nY los Cifuentes se van a mezclar\ncon la plebe, claro.\n\n397\n00:22:52.720 --> 00:22:53.800  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nYa les toca, ¿no?\n\n398\n00:22:53.880 --> 00:22:57.480  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nYo no creo que pueda ir. Es que a mí\nno me gustan mucho las fiestas.\n\n399\n00:22:58.040 --> 00:23:00.400  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nMarga, para decir\nque no te gustan las fiestas\n\n400\n00:23:00.560 --> 00:23:03.080  position:50.00%,middle  align:middle size:80.00%  line:79.33% \ntienes que haber ido\nal menos a alguna en tu vida,\n\n401\n00:23:03.240 --> 00:23:04.280  position:50.00%,middle  align:middle size:80.00%  line:84.67% \ny tú tienes pinta\n\n402\n00:23:04.440 --> 00:23:06.160  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nde no haber ido a ninguna.\n\n403\n00:23:06.320 --> 00:23:07.800  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- Venga, vamos a brindar.\n- [Ángeles] Sí.\n\n404\n00:23:07.960 --> 00:23:09.120  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nVamos. Vamos, Lidia.\n\n405\n00:23:09.280 --> 00:23:11.720  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- [Ángeles] Ay, sí, vamos.\n- [Carlota] Vamos a brindar por Marga\n\n406\n00:23:11.880 --> 00:23:13.520  position:50.00%,middle  align:middle size:80.00%  line:84.67% \ny su primer vermú, por Ángeles,\n\n407\n00:23:13.680 --> 00:23:15.280  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- que gracias a tu ayuda...\n- No, no, no.\n\n408\n00:23:15.440 --> 00:23:17.080  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n...hemos tenido esta oportunidad.\n\n409\n00:23:17.240 --> 00:23:18.960  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nY por las nuevas chicas del cable.\n\n410\n00:23:19.120 --> 00:23:20.080  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- [Ángeles] ¡Sí!\n- Chinchín.\n\n411\n00:23:22.800 --> 00:23:26.120  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nAh, y por que a partir de ahora\nvamos a ser mujeres independientes.\n\n412\n00:23:26.640 --> 00:23:27.840  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[hombre] Carlota...\n\n413\n00:23:31.720 --> 00:23:32.880  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nCoge tus cosas\n\n414\n00:23:33.040 --> 00:23:35.200  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- y ven conmigo ahora mismo.\n- No.\n\n415\n00:23:35.720 --> 00:23:37.320  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nNo tengo que ir a ningún sitio.\n\n416\n00:23:37.480 --> 00:23:39.840  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nTengo trabajo\ny soy una mujer independiente.\n\n417\n00:23:42.640 --> 00:23:45.480  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nQue me suelte, que no soy\nninguno de sus soldados. Suélteme.\n\n418\n00:23:45.880 --> 00:23:47.600  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- [Miguel] Don Emilio.\n- Y tú no te metas.\n\n419\n00:23:47.760 --> 00:23:49.400  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nNo eres nadie en esta familia.\n\n420\n00:23:49.600 --> 00:23:53.000  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- Me va a tener que meter a la fuerza.\n- ¿Pensaste que no iba a enterarme?\n\n421\n00:23:53.160 --> 00:23:55.880  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n¿Se puede saber cuándo\nte has convertido en una mentirosa?\n\n422\n00:23:56.040 --> 00:23:58.360  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n[Carlota] Desde el momento\nque le da igual lo que yo quiera.\n\n423\n00:23:58.520 --> 00:24:01.200  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nNo quiero un marido, quiero\nun trabajo y ser independiente.\n\n424\n00:24:01.360 --> 00:24:03.680  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nUna señorita de tu categoría no trabaja.\n\n425\n00:24:03.840 --> 00:24:06.120  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nDeja de decir tonterías y sube al coche.\n\n426\n00:24:07.400 --> 00:24:08.760  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¡He dicho que entres!\n\n427\n00:24:13.200 --> 00:24:14.800  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nA sus órdenes, mi coronel.\n\n428\n00:24:21.160 --> 00:24:24.560  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- Así que ese es el...\n- Padre de Carlota, sí.\n\n429\n00:24:27.440 --> 00:24:31.040  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nBueno, yo mejor me voy a casa,\nque tengo a mi marido esperándome.\n\n430\n00:24:31.200 --> 00:24:33.280  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- ¿Sabes cómo llegar al hostal?\n- Sí.\n\n431\n00:24:33.440 --> 00:24:36.640  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nCarlota me contó cómo llegar\ndesde aquí hasta la calle Blancaró.\n\n432\n00:24:36.800 --> 00:24:39.080  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- Muy bien. Bueno, hasta mañana.\n- Hasta mañana.\n\n433\n00:24:39.240 --> 00:24:41.600  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¡Ángeles! Espera, que te acompaño.\n\n434\n00:24:46.880 --> 00:24:49.600  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nQue corra el champán.\nY lo que necesiten los señores.\n\n435\n00:24:49.760 --> 00:24:52.520  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nSupongo que estás aquí\nporque lo has conseguido, ¿no?\n\n436\n00:24:52.680 --> 00:24:55.800  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nTengo el trabajo\ny sé dónde está la caja...\n\n437\n00:24:55.960 --> 00:24:58.560  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nPero... me ha surgido un problema,\nhe visto a Francisco.\n\n438\n00:24:58.720 --> 00:25:00.360  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- [Victoria] ¿Qué Francisco?\n- Mi Francisco.\n\n439\n00:25:00.520 --> 00:25:02.400  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- [Victoria] ¿Qué?\n- Es el director de la compañía.\n\n440\n00:25:02.560 --> 00:25:04.120  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- [Victoria] Pero ¿él te ha visto?\n- Sí.\n\n441\n00:25:04.280 --> 00:25:06.840  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n[Victoria]\nTienes que salir de ahí inmediatamente.\n\n442\n00:25:07.000 --> 00:25:09.920  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n[Alba] No puedo.\nSi no pago lo que debo, me condenarán.\n\n443\n00:25:12.200 --> 00:25:16.440  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n[Victoria] Tú ya sabes que si yo tuviera\nesa cantidad. Tú ya me conoces.\n\n444\n00:25:17.360 --> 00:25:19.200  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nVictoria, voy a hacerlo esta noche.\n\n445\n00:25:19.760 --> 00:25:22.200  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nUna de las chicas\nme ha dicho que hay seguridad,\n\n446\n00:25:22.360 --> 00:25:23.920  position:50.00%,middle  align:middle size:80.00%  line:84.67% \npero podré, podré hacerlo.\n\n447\n00:25:24.360 --> 00:25:27.280  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nTengo que ir a la fiesta,\ncoger las llaves, llevarme el dinero\n\n448\n00:25:27.440 --> 00:25:29.680  position:50.00%,middle  align:middle size:80.00%  line:79.33% \ny mañana por la mañana\nestaré muy lejos de aquí.\n\n449\n00:25:30.200 --> 00:25:31.760  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nY de Francisco también...\n\n450\n00:25:32.920 --> 00:25:34.680  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nAlba, yo creo que...\n\n451\n00:25:34.880 --> 00:25:37.040  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nLo único que tengo que hacer\nes ser rápida.\n\n452\n00:25:38.000 --> 00:25:40.120  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nY si me lo encuentro, lo esquivo.\n\n453\n00:25:40.720 --> 00:25:43.960  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nAlba, las prisas\nnunca han sido buenas consejeras.\n\n454\n00:25:44.320 --> 00:25:46.040  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nEs una locura.\n\n455\n00:25:46.960 --> 00:25:49.000  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nVictoria, es eso o el garrote.\n\n456\n00:25:51.160 --> 00:25:52.240  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nAh.\n\n457\n00:25:54.640 --> 00:25:55.800  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nLa 27.\n\n458\n00:25:56.280 --> 00:25:57.320  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nVen aquí.\n\n459\n00:25:59.240 --> 00:26:03.680  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nAlba, cariño, ya perdí a Gimena,\nno quisiera perderte a ti también.\n\n460\n00:26:24.600 --> 00:26:26.840  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>La cena se sirve a las ocho y media</i>\n\n461\n00:26:27.000 --> 00:26:28.520  position:50.00%,middle  align:middle size:80.00%  line:84.67% \ny la puerta se cierra a las once.\n\n462\n00:26:28.680 --> 00:26:31.200  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nSé que no tengo que preocuparme\npor tu formalidad.\n\n463\n00:26:31.360 --> 00:26:33.720  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nTu abuela me ha asegurado\nque eres responsable.\n\n464\n00:26:33.880 --> 00:26:37.000  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nEsta es una pensión decente,\ny ahora tu casa.\n\n465\n00:26:37.160 --> 00:26:38.160  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- Ya.\n- Ven.\n\n466\n00:26:42.240 --> 00:26:46.560  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nMira, sobre la cama tienes un juego\nde sábanas y uno de toallas,\n\n467\n00:26:46.720 --> 00:26:49.760  position:50.00%,middle  align:middle size:80.00%  line:79.33% \npara que las uses\nhasta que compres las tuyas.\n\n468\n00:26:49.920 --> 00:26:50.920  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nBuenas noches.\n\n469\n00:26:51.080 --> 00:26:53.000  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nDoña Lola, verá, es que...\n\n470\n00:26:53.480 --> 00:26:55.480  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nesta noche es\nla inauguración de la empresa\n\n471\n00:26:55.640 --> 00:26:57.640  position:50.00%,middle  align:middle size:80.00%  line:84.67% \ny han invitado a las nuevas telefonistas.\n\n472\n00:26:57.840 --> 00:27:00.000  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nLe prometo que llego\nantes de que cierre la puerta.\n\n473\n00:27:00.160 --> 00:27:01.480  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nAh, bien. Ten cuidado.\n\n474\n00:27:01.640 --> 00:27:03.440  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nSiempre hay un joven desalmado\n\n475\n00:27:03.600 --> 00:27:06.880  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nesperando para aprovecharse\nde una jovencita inocente.\n\n476\n00:27:07.040 --> 00:27:09.480  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nYa sabes, mente abierta, piernas cerradas.\n\n477\n00:27:09.640 --> 00:27:11.360  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- Buenas noches.\n- Buenas noches.\n\n478\n00:27:21.440 --> 00:27:23.280  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[riendo] ¿Qué? ¿Qué? ¿Qué? ¿Qué?\n\n479\n00:27:23.800 --> 00:27:26.320  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nEstás hablando con el nuevo jefe\ntécnico de la central\n\n480\n00:27:26.480 --> 00:27:29.120  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nde la compañía de telefonía\nmás importante de este país.\n\n481\n00:27:30.200 --> 00:27:31.920  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nPero ¿cuándo ha sido? ¿Cuándo ha sido?\n\n482\n00:27:32.080 --> 00:27:33.760  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nEsta tarde\nme lo ha dicho don Francisco.\n\n483\n00:27:33.920 --> 00:27:35.520  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nDigo: \"Le doy un abrazo al estirado\".\n\n484\n00:27:35.680 --> 00:27:37.080  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- ¡Mario!\n- ¿Qué, mi amor?\n\n485\n00:27:37.240 --> 00:27:39.600  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n¿Qué? No he dicho nada\nque todo el mundo no piense.\n\n486\n00:27:39.760 --> 00:27:41.440  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- Ay, qué bien.\n- Vamos a pagar la casa.\n\n487\n00:27:41.600 --> 00:27:44.120  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nVas a dejar de trabajar.\nSe acabaron los problemas.\n\n488\n00:27:44.280 --> 00:27:45.560  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¿Entiendes esto, amor?\n\n489\n00:27:45.720 --> 00:27:47.720  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nTe quiero. Vamos a celebrar.\n\n490\n00:27:49.560 --> 00:27:50.920  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¡Feliz, feliz!\n\n491\n00:27:51.600 --> 00:27:52.800  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nSí...\n\n492\n00:27:52.960 --> 00:27:55.800  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nMario, y... ¿Quieres que deje de trabajar?\n\n493\n00:27:55.960 --> 00:27:57.280  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nLo que habíamos hablado.\n\n494\n00:27:58.200 --> 00:27:59.280  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nYa, ya.\n\n495\n00:27:59.440 --> 00:28:01.520  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nSí, sí, sí, sé que lo hablamos, pero...\n\n496\n00:28:02.680 --> 00:28:05.960  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nEh. Pero es que eso era antes y...\n\n497\n00:28:07.240 --> 00:28:09.560  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nMario, a mí me gusta mucho mi trabajo.\n\n498\n00:28:11.000 --> 00:28:14.520  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n¿Te gusta tu trabajo más que estar\nen casa con tu marido y con tu hija?\n\n499\n00:28:14.680 --> 00:28:18.720  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nNo, Mario, mi hija y tú\nsois mi prioridad, eso siempre.\n\n500\n00:28:18.880 --> 00:28:21.240  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nSi somos tu prioridad,\n¿qué haces por ahí tomando vermú\n\n501\n00:28:21.400 --> 00:28:23.120  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nmientras nosotros estamos en casa?\n\n502\n00:28:23.280 --> 00:28:25.680  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nMario, por Dios,\nes la primera vez en tres años.\n\n503\n00:28:32.320 --> 00:28:33.360  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nMario...\n\n504\n00:28:39.520 --> 00:28:40.680  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[portazo]\n\n505\n00:28:41.160 --> 00:28:42.360  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[suspira]\n\n506\n00:28:50.320 --> 00:28:51.960  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¿No vas a bajar a cenar?\n\n507\n00:28:53.760 --> 00:28:55.880  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nEsto lo hacemos por tu bien, hija.\n\n508\n00:28:56.520 --> 00:28:58.800  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n¿Y no ha pensado, madre,\nque a lo mejor se equivoca\n\n509\n00:28:58.960 --> 00:29:00.200  position:50.00%,middle  align:middle size:80.00%  line:84.67% \ncon lo que es mejor para mí?\n\n510\n00:29:21.960 --> 00:29:24.480  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[música festiva y ambiente animado]\n\n511\n00:29:47.240 --> 00:29:49.640  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- [Marga] Madre mía, cuánta gente.\n- 800 trabajadores...\n\n512\n00:29:49.800 --> 00:29:52.080  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nCon que haya venido solo\nuna cuarta parte...\n\n513\n00:29:52.240 --> 00:29:54.920  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nSi es que yo sabía\nque esto no podía perdérmelo...\n\n514\n00:29:55.080 --> 00:29:56.520  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[Marga] Aún no me creo que hayas venido.\n\n515\n00:29:56.680 --> 00:29:59.800  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nEsta tarde, cuando tu padre entró\nen el bar, casi entro yo en el coche\n\n516\n00:29:59.960 --> 00:30:01.200  position:50.00%,middle  align:middle size:80.00%  line:84.67% \ndel miedo que me dio.\n\n517\n00:30:01.360 --> 00:30:04.640  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n¿Tú sabes cuál es el peor enemigo\nde las mujeres, Marga? La sumisión.\n\n518\n00:30:04.800 --> 00:30:08.320  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nBueno, a mí siempre\nme han enseñado a obedecer.\n\n519\n00:30:08.480 --> 00:30:11.560  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nYa, y a mí. \"Una mujer siempre\ntiene que ser correcta y obediente\".\n\n520\n00:30:11.720 --> 00:30:14.640  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nPero ¿sabes qué? Que un día pensé:\n\"Pero si tú no eres una mujer\n\n521\n00:30:14.800 --> 00:30:16.320  position:50.00%,middle  align:middle size:80.00%  line:84.67% \npara saber lo que yo necesito\".\n\n522\n00:30:16.480 --> 00:30:19.720  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nPuede cerrar todas las puertas\nque quiera porque \"no hay barrera,\n\n523\n00:30:19.880 --> 00:30:23.240  position:50.00%,middle  align:middle size:80.00%  line:79.33% \ncerradura ni cerrojo que puedas\nimponer a la libertad de mi mente\".\n\n524\n00:30:23.400 --> 00:30:27.040  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- Lo dijo Virginia Woolf.\n- ¿Esa es amiga tuya?\n\n525\n00:30:28.080 --> 00:30:29.840  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[aplausos]\n\n526\n00:30:31.880 --> 00:30:33.960  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[Carmen] Ni que fuéramos de la realeza.\n\n527\n00:30:34.120 --> 00:30:36.560  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n¿Desde cuándo te molesta\nser el centro de atención?\n\n528\n00:30:36.720 --> 00:30:38.400  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¿Quién ha dicho que me moleste?\n\n529\n00:30:38.680 --> 00:30:41.400  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n¿Crees que alguna vez\nalgo te parecerá bien, querida?\n\n530\n00:30:41.560 --> 00:30:44.880  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nSí, me pareció bien\ncasarme contigo. Al principio.\n\n531\n00:30:45.040 --> 00:30:46.720  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nVoy a saludar, ahora les veo.\n\n532\n00:30:51.480 --> 00:30:53.200  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[música de la fiesta]\n\n533\n00:31:03.520 --> 00:31:04.720  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[risas]\n\n534\n00:31:25.400 --> 00:31:26.440  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nBuenas noches.\n\n535\n00:31:27.040 --> 00:31:28.080  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nDisculpe.\n\n536\n00:31:28.240 --> 00:31:29.960  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nSeñorita... ¿Cómo era?\n\n537\n00:31:32.360 --> 00:31:34.000  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- Aguilar. [ríe]\n- Aguilar, eso es.\n\n538\n00:31:34.960 --> 00:31:37.440  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- [Carlos] Qué agradable sorpresa...\n- [Alba] Sí, ya he visto\n\n539\n00:31:37.600 --> 00:31:39.440  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nque lo estaba pasando realmente mal.\n\n540\n00:31:39.600 --> 00:31:41.040  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nAh, ni siquiera he tenido tiempo.\n\n541\n00:31:41.200 --> 00:31:42.800  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nHay que ser amable con los empleados.\n\n542\n00:31:42.960 --> 00:31:44.920  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nEso es lo que hace conmigo,\nser amable...\n\n543\n00:31:45.080 --> 00:31:47.960  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nHay cosas que se hacen\npor obligación y otras por placer.\n\n544\n00:31:48.120 --> 00:31:49.160  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nClaramente\n\n545\n00:31:49.320 --> 00:31:50.760  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nesta es una de las segundas.\n\n546\n00:31:53.040 --> 00:31:55.680  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nVeo que esta noche\nestá resultando divertida.\n\n547\n00:31:55.840 --> 00:31:58.480  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nSeñorita Aguilar,\nle presento a Francisco Gómez.\n\n548\n00:31:58.640 --> 00:32:00.600  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- Nos conocimos antes.\n- Sí.\n\n549\n00:32:01.680 --> 00:32:03.200  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- ¿Quiere tomar algo?\n- No, gracias.\n\n550\n00:32:03.360 --> 00:32:05.640  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n¿Un <i>white lady</i>?\nLa bebida de las chicas de ciudad.\n\n551\n00:32:05.800 --> 00:32:07.640  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nEsta noche se merece un buen brindis.\n\n552\n00:32:07.800 --> 00:32:10.680  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nY se lo agradezco,\npero no me gusta el <i>white lady</i>.\n\n553\n00:32:10.840 --> 00:32:12.200  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nEso se llama sinceridad.\n\n554\n00:32:12.360 --> 00:32:14.840  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nEs una cualidad muy poco extendida,\npor cierto.\n\n555\n00:32:15.000 --> 00:32:16.600  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nResulta que la señorita Aguilar\n\n556\n00:32:16.760 --> 00:32:19.720  position:50.00%,middle  align:middle size:80.00%  line:79.33% \ntiene de sobra para ti y para mí,\nademás de otras muchas virtudes.\n\n557\n00:32:19.880 --> 00:32:21.120  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¿Cuáles?\n\n558\n00:32:21.280 --> 00:32:22.960  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[para la música]\n\n559\n00:32:23.120 --> 00:32:26.080  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nMe parece que vamos a tener\nque esperar para conocerlas.\n\n560\n00:32:26.240 --> 00:32:27.480  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nCariño...\n\n561\n00:32:30.000 --> 00:32:33.400  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nMi padre me ha pedido que os avise.\nOs espera para subir al escenario.\n\n562\n00:32:37.040 --> 00:32:39.680  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n[Carlos] Ni se mueva, señorita Aguilar,\naún me debe un baile.\n\n563\n00:32:43.040 --> 00:32:45.440  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n[Ricardo] Quiero agradecer\na todos los presentes\n\n564\n00:32:45.600 --> 00:32:48.800  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nque hayáis venido esta noche\na compartir con nosotros\n\n565\n00:32:48.960 --> 00:32:52.560  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nla inauguración de la mayor central\nde telefonía de Europa.\n\n566\n00:32:52.720 --> 00:32:56.160  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nTodos sabéis que no ha sido\nun camino fácil ni corto\n\n567\n00:32:56.320 --> 00:32:59.560  position:50.00%,middle  align:middle size:80.00%  line:79.33% \ny que estas canas están directamente\nrelacionadas con este camino.\n\n568\n00:32:59.720 --> 00:33:01.800  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nPero ya estamos aquí.\n\n569\n00:33:01.960 --> 00:33:03.320  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nY no lo estaríamos si no fuese\n\n570\n00:33:03.480 --> 00:33:06.440  position:50.00%,middle  align:middle size:80.00%  line:79.33% \npor la persona que ha impulsado\npersonalmente este proyecto.\n\n571\n00:33:07.360 --> 00:33:08.480  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nEs leal,\n\n572\n00:33:08.640 --> 00:33:10.680  position:50.00%,middle  align:middle size:80.00%  line:84.67% \ntrabajador, honesto\n\n573\n00:33:11.040 --> 00:33:13.360  position:50.00%,middle  align:middle size:80.00%  line:84.67% \ny tengo la tranquilidad de saber\n\n574\n00:33:13.520 --> 00:33:16.840  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nque dejo el futuro de la compañía\nen manos de mi yerno,\n\n575\n00:33:17.000 --> 00:33:19.040  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nal que ya considero como mi propio hijo.\n\n576\n00:33:19.200 --> 00:33:20.600  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nFrancisco Gómez. Francisco.\n\n577\n00:33:28.320 --> 00:33:29.320  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[Francisco] Gracias.\n\n578\n00:33:29.480 --> 00:33:30.560  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nGracias.\n\n579\n00:33:30.720 --> 00:33:32.280  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nHace 10 años, ni siquiera\n\n580\n00:33:32.440 --> 00:33:34.120  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nhubiera imaginado estar hoy aquí.\n\n581\n00:33:37.200 --> 00:33:38.760  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nMe conformaba con un buen trabajo\n\n582\n00:33:38.920 --> 00:33:41.440  position:50.00%,middle  align:middle size:80.00%  line:79.33% \ny una habitación que compartir\ncon el amor de mi vida.\n\n583\n00:33:44.680 --> 00:33:47.280  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nHoy tengo casi todo aquello\ncon lo que había soñado.\n\n584\n00:33:48.320 --> 00:33:50.360  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nCasi, porque siempre se puede\n\n585\n00:33:50.520 --> 00:33:51.800  position:50.00%,middle  align:middle size:80.00%  line:84.67% \ndesear algo más.\n\n586\n00:33:52.560 --> 00:33:55.120  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nHoy es el principio\nde una nueva era para la compañía.\n\n587\n00:33:55.280 --> 00:33:57.240  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nUna era que va a traspasar océanos.\n\n588\n00:33:57.400 --> 00:34:00.640  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nMe complace anunciar que esta\ncompañía va a realizar mañana\n\n589\n00:34:00.800 --> 00:34:03.000  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nla primera llamada intercontinental.\n\n590\n00:34:03.160 --> 00:34:05.440  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nEl presidente Coolidge\ny su majestad Alfonso XIII\n\n591\n00:34:05.600 --> 00:34:07.840  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nestablecerán\nla primera conexión de la historia\n\n592\n00:34:08.000 --> 00:34:11.120  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nentre España\ny los Estados Unidos de América.\n\n593\n00:34:19.080 --> 00:34:23.320  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n[Alba] <i>Había intentado convencerme</i>\n<i>durante años de que Francisco</i>\n\n594\n00:34:23.480 --> 00:34:25.239  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>ya no significaba nada para mí.</i>\n\n595\n00:34:25.400 --> 00:34:28.800  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n<i>Si quería ser libre, no debía</i>\n<i>dejarme llevar por el corazón.</i>\n\n596\n00:34:34.159 --> 00:34:35.360  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>Esa noche</i>\n\n597\n00:34:35.520 --> 00:34:38.760  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n<i>robaría el dinero de la compañía</i>\n<i>y huiría lejos</i>\n\n598\n00:34:38.920 --> 00:34:41.639  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n<i>de cualquier fantasma del pasado,</i>\n<i>bueno o malo,</i>\n\n599\n00:34:42.080 --> 00:34:44.280  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>para ser... simplemente yo.</i>\n\n600\n00:34:44.440 --> 00:34:46.679  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nDisculpe, señorita, su identificación.\n\n601\n00:34:53.400 --> 00:34:54.800  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nAquí pone \"turno de día\".\n\n602\n00:34:54.960 --> 00:34:56.679  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nNo se permite el paso a ningún empleado\n\n603\n00:34:56.840 --> 00:34:58.400  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- que no sea del turno de noche.\n- Ya, ya.\n\n604\n00:34:58.560 --> 00:35:01.000  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nPero será solo un momento.\nMe he dejado el bolso.\n\n605\n00:35:01.160 --> 00:35:03.320  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nLo siento,\npero tendrá que recogerlo mañana.\n\n606\n00:35:04.640 --> 00:35:06.720  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nEs que me he dejado las llaves dentro.\n\n607\n00:35:09.200 --> 00:35:11.040  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nY no tengo a nadie a quien llamar.\n\n608\n00:35:12.000 --> 00:35:13.400  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nHágame el favor.\n\n609\n00:35:14.160 --> 00:35:17.040  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nO, si no, me voy a quedar\ntoda la noche en la calle. Será...\n\n610\n00:35:17.200 --> 00:35:18.480  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nSerá solo un momento.\n\n611\n00:36:06.960 --> 00:36:09.640  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nDebemos ser los únicos a los\nque no han invitado a la fiesta.\n\n612\n00:36:09.800 --> 00:36:12.000  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nJulián dice que han ido\nhasta los mozos de carga.\n\n613\n00:36:12.160 --> 00:36:13.720  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[puerta]\n\n614\n00:36:19.080 --> 00:36:20.080  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[música]\n\n615\n00:36:20.240 --> 00:36:21.600  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nEsta me encanta. ¿La conoces?\n\n616\n00:36:21.760 --> 00:36:23.600  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- No.\n- Bueno, pues si tienes\n\n617\n00:36:23.760 --> 00:36:26.480  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nun mal día, te pones esta canción\ny todos tus males se te pasan.\n\n618\n00:36:26.640 --> 00:36:29.080  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- Mira, escucha.\n- Creo que las hay mejores que esta,\n\n619\n00:36:29.240 --> 00:36:31.960  position:50.00%,middle  align:middle size:80.00%  line:79.33% \npero si esta consigue\nque te olvides de tus problemas...\n\n620\n00:36:32.120 --> 00:36:34.480  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- ¿Cómo has salido del cuartel?\n- Por la ventana.\n\n621\n00:36:34.640 --> 00:36:36.240  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nQué dura es la vida del soldado.\n\n622\n00:36:36.400 --> 00:36:38.400  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nMenos mal que las noches son\n\n623\n00:36:38.560 --> 00:36:39.680  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nmucho más alegres.\n\n624\n00:36:39.840 --> 00:36:41.160  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nVenga, vamos a bailar.\n\n625\n00:37:06.000 --> 00:37:07.480  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[jadeos]\n\n626\n00:37:41.920 --> 00:37:43.960  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- ¡Ah!\n- ¡Eh! ¡Oiga!\n\n627\n00:37:44.520 --> 00:37:45.600  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nDeténgase.\n\n628\n00:37:47.000 --> 00:37:48.320  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[gruñe]\n\n629\n00:37:58.520 --> 00:37:59.840  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¿Está usted bien?\n\n630\n00:38:03.680 --> 00:38:06.560  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nNo he podido atraparle, pero\nal menos he conseguido su bolso.\n\n631\n00:38:06.720 --> 00:38:07.840  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nCreo que está todo.\n\n632\n00:38:33.080 --> 00:38:34.240  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[Carlota] ¡Ah!\n\n633\n00:38:40.960 --> 00:38:42.640  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n[risita] A ver qué excusa\nme invento mañana\n\n634\n00:38:42.800 --> 00:38:45.080  position:50.00%,middle  align:middle size:80.00%  line:79.33% \npara salir de aquí\ny llegar a tiempo al turno.\n\n635\n00:38:45.240 --> 00:38:48.000  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nSabes que no puedes estar así\ntoda la vida...\n\n636\n00:38:48.160 --> 00:38:50.280  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nYa, pero es que no me queda\notra alternativa.\n\n637\n00:38:50.440 --> 00:38:51.720  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- Sí que la tienes.\n- Ah, ¿sí?\n\n638\n00:38:51.880 --> 00:38:52.840  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nCásate conmigo.\n\n639\n00:38:53.000 --> 00:38:54.200  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[riendo] Estás loco.\n\n640\n00:38:54.360 --> 00:38:56.960  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nSí, yo tampoco pensé nunca\nque te fuese a decir esto,\n\n641\n00:38:57.120 --> 00:38:58.160  position:50.00%,middle  align:middle size:80.00%  line:84.67% \npero es la solución.\n\n642\n00:38:58.320 --> 00:39:00.400  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nAh, que es la solución, ¿eh? Sí.\n\n643\n00:39:02.640 --> 00:39:05.440  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- No dependerías de tu padre.\n- No, no dependería de mi padre.\n\n644\n00:39:05.600 --> 00:39:07.000  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nDependería de ti, mi marido,\n\n645\n00:39:07.160 --> 00:39:09.400  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nque es el perfecto sinónimo\nde independencia.\n\n646\n00:39:09.560 --> 00:39:12.040  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nY te crees que yo te voy a decir\nlo que tienes que hacer...\n\n647\n00:39:12.840 --> 00:39:14.320  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nEstás borracho, me voy a casa.\n\n648\n00:39:14.480 --> 00:39:16.960  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nSí, estoy borracho, pero tengo razón.\n\n649\n00:39:17.280 --> 00:39:18.920  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nPiénsatelo.\n\n650\n00:39:26.480 --> 00:39:28.440  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[motor a lo lejos]\n\n651\n00:39:29.840 --> 00:39:31.040  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[hombre] ¡Vamos, Miguel!\n\n652\n00:39:32.680 --> 00:39:34.080  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[Miguel] Buenas noches.\n\n653\n00:39:34.320 --> 00:39:35.800  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nEh, esperadme, chicos.\n\n654\n00:39:50.920 --> 00:39:52.640  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[pequeños golpes]\n\n655\n00:40:00.320 --> 00:40:01.520  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[suspira]\n\n656\n00:40:07.560 --> 00:40:08.760  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nPerdona. No hagas ruido.\n\n657\n00:40:08.920 --> 00:40:11.640  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nGracias, Marga.\nEs que no sabía dónde estaba Miguel.\n\n658\n00:40:11.800 --> 00:40:14.480  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nNo te preocupes, hay dos camas,\ny las dos son para ti si quieres.\n\n659\n00:40:14.640 --> 00:40:16.240  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- Yo mañana me voy al pueblo.\n- ¿Por qué?\n\n660\n00:40:16.400 --> 00:40:18.000  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nPorque esto no es para mí, Carlota.\n\n661\n00:40:18.160 --> 00:40:20.760  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nMe he perdido, se me ha roto\nla maleta, me han robado el bolso.\n\n662\n00:40:20.920 --> 00:40:22.440  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- ¿Te han robado?\n- Sí, pero da igual.\n\n663\n00:40:22.600 --> 00:40:23.960  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nYo no quiero estar aquí.\n\n664\n00:40:24.120 --> 00:40:26.760  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nAy, Marga, ¿tú sabes\ncuánto tiempo estuve fingiendo\n\n665\n00:40:26.920 --> 00:40:28.320  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nque iba a clase de labores?\n\n666\n00:40:28.600 --> 00:40:29.880  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nUn año.\n\n667\n00:40:30.040 --> 00:40:32.400  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nUn año mientras me pagaba\nlas clases de mecanografía.\n\n668\n00:40:32.560 --> 00:40:35.800  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n¿Y por qué? No quería que mis padres\nse enteraran de que quería trabajar.\n\n669\n00:40:35.960 --> 00:40:37.640  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nTenía miedo de que me echaran de casa.\n\n670\n00:40:39.320 --> 00:40:40.600  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nVaya, lo siento.\n\n671\n00:40:41.440 --> 00:40:42.760  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nPero ¿lo siento por qué?\n\n672\n00:40:43.560 --> 00:40:45.120  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nDe lo siento nada, no.\n\n673\n00:40:45.520 --> 00:40:48.440  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n¿Sabes cuál es el lado bueno?\nQue ya no tengo miedo.\n\n674\n00:40:50.160 --> 00:40:51.080  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nDe verdad, Carlota,\n\n675\n00:40:51.240 --> 00:40:53.560  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nque no sé cómo te puedes\ntomar las cosas así de bien.\n\n676\n00:40:53.720 --> 00:40:55.840  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n¿Y qué quieres que haga,\nque me ponga a llorar\n\n677\n00:40:56.000 --> 00:40:58.760  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nporque mis padres prefieren\nsus ideas a una hija como yo?\n\n678\n00:40:58.920 --> 00:41:00.680  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¿De qué iba a servir? De nada. Mira.\n\n679\n00:41:00.840 --> 00:41:02.400  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nHay dos maneras de ver la vida.\n\n680\n00:41:02.560 --> 00:41:05.440  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nPuedes ver el lado negativo,\nponerte a llorar, protestar...\n\n681\n00:41:05.600 --> 00:41:07.000  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nO puedes ver el lado divertido,\n\n682\n00:41:07.160 --> 00:41:09.240  position:50.00%,middle  align:middle size:80.00%  line:84.67% \ndisfrutar, sonreír, y tirar hacia delante.\n\n683\n00:41:09.400 --> 00:41:10.800  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nY ese es el que he elegido yo.\n\n684\n00:41:12.440 --> 00:41:15.120  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nTodo en la vida tiene algo bueno,\nhasta Madrid.\n\n685\n00:41:16.280 --> 00:41:18.480  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nAunque... no lo veas.\n\n686\n00:41:22.160 --> 00:41:24.600  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nSi no robo esa caja durante la llamada,\n\n687\n00:41:25.720 --> 00:41:28.920  position:50.00%,middle  align:middle size:80.00%  line:79.33% \ncreo que vas a tener\nque buscarte otro hogar.\n\n688\n00:41:31.480 --> 00:41:33.400  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nBeltrán no me va a dar más tiempo.\n\n689\n00:41:35.520 --> 00:41:37.600  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nO entrego ese dinero mañana a la una...\n\n690\n00:41:39.480 --> 00:41:41.160  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nEsta es mi última oportunidad.\n\n691\n00:41:43.040 --> 00:41:46.200  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nExtra, extra. Hoy se realiza\nla primera llamada a América.\n\n692\n00:41:46.360 --> 00:41:49.960  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nExtra, extra.\nHoy el rey llamará a América.\n\n693\n00:42:00.200 --> 00:42:01.880  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nMario, ¿puedo hablar contigo?\n\n694\n00:42:02.040 --> 00:42:04.520  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- Tengo mucho trabajo, ahora no.\n- He estado toda la noche\n\n695\n00:42:04.680 --> 00:42:06.560  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nen vilo sin saber si estabas bien.\n\n696\n00:42:07.120 --> 00:42:09.040  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- ¿Dónde has estado?\n- Caminando.\n\n697\n00:42:10.320 --> 00:42:11.640  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nToda la noche...\n\n698\n00:42:11.800 --> 00:42:14.160  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nToda la noche. Tenía muchas cosas\nen las que pensar.\n\n699\n00:42:15.480 --> 00:42:16.520  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nMario...\n\n700\n00:42:16.680 --> 00:42:19.560  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nÁngeles, no voy a volver\na discutir contigo y menos aquí.\n\n701\n00:42:20.120 --> 00:42:23.720  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nEs que no quiero discutir,\nde verdad, solo quiero que hablemos.\n\n702\n00:42:23.880 --> 00:42:25.000  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nPor favor.\n\n703\n00:42:35.320 --> 00:42:36.360  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¿Quieres hablar?\n\n704\n00:42:37.480 --> 00:42:38.520  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nHabla.\n\n705\n00:42:39.120 --> 00:42:41.600  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nMario, de verdad, ¿tú no puedes entender\n\n706\n00:42:41.760 --> 00:42:45.080  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nque me haya molestado\nque me pidas que deje mi trabajo?\n\n707\n00:42:45.240 --> 00:42:47.400  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nNo me lo puedo creer.\nPero ¿tú qué te piensas,\n\n708\n00:42:47.560 --> 00:42:50.560  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nque yo no me he dado cuenta\nde lo mucho que te gusta tu trabajo?\n\n709\n00:42:50.720 --> 00:42:53.000  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¿Lo que te está costando dejar todo esto?\n\n710\n00:42:53.800 --> 00:42:55.320  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nPero nosotros tenemos una hija,\n\n711\n00:42:55.480 --> 00:42:58.400  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nÁngeles, y yo no quiero que\na mi hija la cuide una desconocida,\n\n712\n00:42:58.560 --> 00:42:59.960  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nquiero que la cuide su madre.\n\n713\n00:43:00.120 --> 00:43:01.640  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¿Te has parado a pensar lo que sufro\n\n714\n00:43:01.800 --> 00:43:04.080  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nporque no le puedo dar a mi familia\nlo que se merece?\n\n715\n00:43:04.240 --> 00:43:06.080  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nTe prometí que no te iba a faltar de nada,\n\n716\n00:43:06.240 --> 00:43:07.720  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nque te iba a tratar como una reina.\n\n717\n00:43:07.880 --> 00:43:10.280  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n¿Y qué he conseguido?\nQue te pases el día trabajando,\n\n718\n00:43:10.440 --> 00:43:11.800  position:50.00%,middle  align:middle size:80.00%  line:84.67% \ncogiendo llamadas.\n\n719\n00:43:15.480 --> 00:43:18.440  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nÁngeles, tú te has convencido\nde que todo esto está bien.\n\n720\n00:43:18.600 --> 00:43:19.680  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nNo lo está.\n\n721\n00:43:22.280 --> 00:43:23.640  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nDéjame hacerte feliz.\n\n722\n00:43:25.080 --> 00:43:26.080  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nPor favor.\n\n723\n00:43:28.960 --> 00:43:31.040  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nSeamos la familia que siempre soñamos ser.\n\n724\n00:43:44.040 --> 00:43:46.400  position:50.00%,middle  align:middle size:80.00%  line:10.00% \n[puerta abriéndose]\n\n725\n00:43:47.320 --> 00:43:48.440  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[Carlos] Buenos días.\n\n726\n00:43:58.120 --> 00:44:01.160  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- ¿Se puede saber qué estás buscando?\n- Las llaves de la caja fuerte,\n\n727\n00:44:01.320 --> 00:44:02.960  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nque me las olvidé aquí o las perdí ayer,\n\n728\n00:44:03.120 --> 00:44:05.040  position:50.00%,middle  align:middle size:80.00%  line:79.33% \ndonde quiera que haya estado\ntoda la noche.\n\n729\n00:44:05.200 --> 00:44:08.240  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nAlgún día deberías de probar\na beber dos copas menos de coñac.\n\n730\n00:44:08.400 --> 00:44:11.080  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- Le vendría bien a tu memoria.\n- Y fatal a mi alma.\n\n731\n00:44:11.240 --> 00:44:13.480  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nEs libre, no puedo estar\nponiéndole cortapisas.\n\n732\n00:44:14.280 --> 00:44:15.360  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nYa.\n\n733\n00:44:15.600 --> 00:44:17.960  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nY tú algún deberías probar\na soltar alguna sonrisa.\n\n734\n00:44:19.600 --> 00:44:20.760  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¿Estás bien?\n\n735\n00:44:23.360 --> 00:44:24.880  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¿Recuerdas a Alba?\n\n736\n00:44:25.040 --> 00:44:26.120  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¿Alba?\n\n737\n00:44:31.480 --> 00:44:33.000  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¿Tu amor de la adolescencia,\n\n738\n00:44:33.160 --> 00:44:35.240  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nla que desapareció sin despedirse,\n\n739\n00:44:35.400 --> 00:44:37.080  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nla que se escapó corriendo de ti?\n\n740\n00:44:37.240 --> 00:44:38.560  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¿Esa? No.\n\n741\n00:44:39.360 --> 00:44:41.440  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- Ayer me pareció verla.\n- ¿Otra vez?\n\n742\n00:44:41.600 --> 00:44:42.720  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nSe parecía mucho.\n\n743\n00:44:43.280 --> 00:44:45.360  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nFrancisco, la gente en diez años cambia.\n\n744\n00:44:46.320 --> 00:44:48.000  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nMucho. Mírate tú.\n\n745\n00:44:48.560 --> 00:44:50.440  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[ríe]\n\n746\n00:44:50.520 --> 00:44:52.080  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nSí, tienes razón, olvídalo.\n\n747\n00:44:52.360 --> 00:44:53.800  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nHa sido una tontería.\n\n748\n00:44:54.480 --> 00:44:56.560  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nAdemás, hay mucho que hacer.\n\n749\n00:44:57.920 --> 00:44:59.440  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¿Lo suficientemente elegante\n\n750\n00:44:59.600 --> 00:45:01.960  position:50.00%,middle  align:middle size:80.00%  line:79.33% \ncomo para ser inmortalizado\njunto a su majestad?\n\n751\n00:45:02.400 --> 00:45:03.640  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nSi no tuvieras esas ojeras,\n\n752\n00:45:03.800 --> 00:45:05.600  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nhasta creería que eres un hombre formal.\n\n753\n00:45:06.720 --> 00:45:08.560  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nHay... mucho que hacer.\n\n754\n00:45:09.120 --> 00:45:10.960  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[pisa fuerte] Orden del día.\n\n755\n00:45:11.120 --> 00:45:12.640  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nAntes de nada, comunicarle a Sara\n\n756\n00:45:12.800 --> 00:45:14.960  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nquién será la encargada\nde efectuar la llamada.\n\n757\n00:45:15.120 --> 00:45:16.160  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nYa me he encargado yo.\n\n758\n00:45:17.160 --> 00:45:18.440  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nPersonalmente.\n\n759\n00:45:24.320 --> 00:45:25.360  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¿Qué?\n\n760\n00:45:25.840 --> 00:45:27.920  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- Siento el retraso.\n- ¿Te lo has pensado mejor?\n\n761\n00:45:28.280 --> 00:45:29.280  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¿Qué está pasando?\n\n762\n00:45:29.440 --> 00:45:32.280  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nAh, van a anunciar la telefonista\nque va a hacer la llamada del rey.\n\n763\n00:45:32.440 --> 00:45:34.840  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nSe lo darán a Ángeles,\nes la que tiene más experiencia.\n\n764\n00:45:35.000 --> 00:45:36.000  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nSeñoritas...\n\n765\n00:45:36.160 --> 00:45:38.400  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nNo vamos a demorar más este momento.\n\n766\n00:45:38.560 --> 00:45:40.080  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nTodas saben que hoy se llevará a cabo\n\n767\n00:45:40.240 --> 00:45:41.920  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nla conexión transoceánica entre el rey\n\n768\n00:45:42.080 --> 00:45:44.280  position:50.00%,middle  align:middle size:80.00%  line:84.67% \ny el presidente de los EE. UU.\n\n769\n00:45:44.440 --> 00:45:47.320  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nHay que designar a la telefonista\nque llevará a cabo dicha conexión.\n\n770\n00:45:47.480 --> 00:45:48.880  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nEs una gran responsabilidad,\n\n771\n00:45:49.040 --> 00:45:51.680  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nasí que espero que la persona\nelegida se lo tome como tal.\n\n772\n00:45:51.840 --> 00:45:55.400  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nLa telefonista elegida es...\nLidia Aguilar.\n\n773\n00:45:55.880 --> 00:45:57.000  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¿Yo?\n\n774\n00:45:58.080 --> 00:45:59.320  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nNo puedo hacerlo.\n\n775\n00:45:59.480 --> 00:46:00.760  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¿Perdone, señorita Aguilar?\n\n776\n00:46:00.920 --> 00:46:04.320  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nAcabo de llegar, no conozco\nel puesto, debería hacerlo alguien\n\n777\n00:46:04.480 --> 00:46:05.440  position:50.00%,middle  align:middle size:80.00%  line:84.67% \ncon más experiencia.\n\n778\n00:46:05.600 --> 00:46:07.520  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- Ángeles, por ejemplo.\n- Estoy de acuerdo.\n\n779\n00:46:07.680 --> 00:46:10.160  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nPero la decisión no ha sido mía,\nson órdenes de Dirección.\n\n780\n00:46:10.320 --> 00:46:12.000  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nEspero que cumpla con su cometido.\n\n781\n00:46:12.840 --> 00:46:14.840  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nAquí tiene, el protocolo de actuación.\n\n782\n00:46:15.000 --> 00:46:17.240  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nApréndaselo\ncomo si le fuese la vida en ello.\n\n783\n00:46:17.400 --> 00:46:18.960  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nPorque le aseguro que le va.\n\n784\n00:46:20.360 --> 00:46:21.480  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nEl resto de centralitas\n\n785\n00:46:21.640 --> 00:46:24.160  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nse desconectarán\ndurante un periodo de 10 minutos.\n\n786\n00:46:24.320 --> 00:46:26.800  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nAsí que todas ustedes\nno tendrán que hacer otra cosa más\n\n787\n00:46:26.960 --> 00:46:28.400  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nque presenciar este momento.\n\n788\n00:46:34.880 --> 00:46:37.520  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- No voy a hacerlo.\n- Señorita, el protocolo es sencillo.\n\n789\n00:46:37.680 --> 00:46:39.760  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nY ayer se manejaba bien con las clavijas.\n\n790\n00:46:39.920 --> 00:46:40.920  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nNo me refiero...\n\n791\n00:46:41.080 --> 00:46:43.960  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nSi falla cualquier cosa, habrá\nmás telefonistas para cubrirla.\n\n792\n00:46:48.400 --> 00:46:50.520  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nEs un momento muy importante\npara la compañía.\n\n793\n00:46:50.680 --> 00:46:53.400  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nVas a ponerlo en peligro\npara conquistar a una telefonista.\n\n794\n00:46:53.560 --> 00:46:55.120  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nMe estás hablando como mi padre.\n\n795\n00:46:55.280 --> 00:46:58.600  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n¿De verdad piensas eso, piensas\nque lo hago solo para conquistarla?\n\n796\n00:46:58.760 --> 00:46:59.760  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nCarlos...\n\n797\n00:46:59.920 --> 00:47:02.200  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nMe gusta la imagen\nque proyecta para la empresa.\n\n798\n00:47:02.360 --> 00:47:04.720  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nVamos, es una chica ambiciosa.\nCreo que lo hará bien.\n\n799\n00:47:04.880 --> 00:47:06.360  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¿Por qué no me consultaste nada?\n\n800\n00:47:06.520 --> 00:47:08.440  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nNo sabía que tenía que consultarte todo.\n\n801\n00:47:10.480 --> 00:47:12.200  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nAdemás, de las selecciones de personal\n\n802\n00:47:12.360 --> 00:47:13.600  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nsiempre me he encargado yo.\n\n803\n00:47:15.680 --> 00:47:17.800  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nConfía en mí, por favor.\n\n804\n00:47:19.520 --> 00:47:21.840  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nLa expectación es máxima\nentre los medios reunidos\n\n805\n00:47:22.000 --> 00:47:24.440  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n<i>en esta décima planta</i>\n<i>de la compañía telefónica.</i>\n\n806\n00:47:24.600 --> 00:47:27.520  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n<i>Hoy, a las 12 en punto del mediodía,</i>\n<i>se producirá</i>\n\n807\n00:47:27.680 --> 00:47:29.720  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>un hecho que marcará un antes y un después</i>\n\n808\n00:47:29.880 --> 00:47:30.880  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>en la historia:</i>\n\n809\n00:47:31.040 --> 00:47:33.640  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n<i>la primera llamada telefónica</i>\n<i>intercontinental realizada</i>\n\n810\n00:47:33.800 --> 00:47:34.880  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>desde nuestro país</i>\n\n811\n00:47:35.040 --> 00:47:37.560  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n<i>y para la que se cuenta</i>\n<i>con dos anfitriones de lujo</i>\n\n812\n00:47:37.720 --> 00:47:39.400  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>a ambos lados del Atlántico.</i>\n\n813\n00:47:41.760 --> 00:47:42.880  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[vítores y aplausos]\n\n814\n00:47:43.040 --> 00:47:44.480  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>Su majestad, Alfonso XIII,</i>\n\n815\n00:47:44.640 --> 00:47:47.280  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n<i>cuya llegada al palacio</i>\n<i>de la Compañía de Telefonía</i>\n\n816\n00:47:47.440 --> 00:47:49.120  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>estamos a punto de presenciar.</i>\n\n817\n00:47:49.280 --> 00:47:51.600  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[vítores y aplausos]\n\n818\n00:47:52.720 --> 00:47:55.360  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n<i>Conversará con el presidente Coolidge</i>\n<i>en una conexión</i>\n\n819\n00:47:55.520 --> 00:47:56.640  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>que no hace sino confirmar</i>\n\n820\n00:47:56.800 --> 00:47:59.280  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n<i>las buenas relaciones existentes</i>\n<i>entre ambos países.</i>\n\n821\n00:48:02.240 --> 00:48:04.040  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[Alba] <i>No tenía miedo a asumir ese reto,</i>\n\n822\n00:48:04.200 --> 00:48:06.920  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n<i>pero hacerlo complicaba</i>\n<i>mi principal objetivo.</i>\n\n823\n00:48:10.120 --> 00:48:12.720  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n<i>En aquel instante</i>\n<i>en el que el mundo entero</i>\n\n824\n00:48:12.880 --> 00:48:16.280  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n<i>estaría pendiente</i>\n<i>del gran acontecimiento histórico,</i>\n\n825\n00:48:17.040 --> 00:48:18.560  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>yo robaría la caja fuerte.</i>\n\n826\n00:48:19.240 --> 00:48:20.840  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>Acabaría con el chantaje de Beltrán</i>\n\n827\n00:48:21.000 --> 00:48:23.920  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n<i>y huiría en busca de la nueva vida</i>\n<i>con la que siempre había soñado,</i>\n\n828\n00:48:24.880 --> 00:48:28.280  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>lejos de mi pasado... y del que un día</i>\n\n829\n00:48:28.440 --> 00:48:30.360  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>había sido el amor de mi vida.</i>\n\n830\n00:48:45.120 --> 00:48:46.600  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nYa es la hora, padre.\n\n831\n00:48:46.920 --> 00:48:48.000  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nBien.\n\n832\n00:48:48.160 --> 00:48:51.440  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nMajestad, por favor,\ntiene el mundo a sus pies.\n\n833\n00:49:11.000 --> 00:49:14.080  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nBuenos días. Compañía de Telefonía,\n¿en qué puedo ayudarle?\n\n834\n00:49:14.240 --> 00:49:16.080  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¿Sí? ¿Operadora?\n\n835\n00:49:16.440 --> 00:49:18.120  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¿Podría hacer el favor\n\n836\n00:49:18.280 --> 00:49:21.480  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nde comunicarme con Washington, EE. UU.?\n\n837\n00:49:21.640 --> 00:49:24.280  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>Número 0002, con el presidente.</i>\n\n838\n00:49:24.440 --> 00:49:26.160  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nPor supuesto, su majestad.\n\n839\n00:49:26.320 --> 00:49:27.400  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nLe comunico.\n\n840\n00:49:27.720 --> 00:49:29.560  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nManténgase a la espera, por favor.\n\n841\n00:49:41.000 --> 00:49:43.040  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[bobina]\n\n842\n00:50:04.720 --> 00:50:06.280  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nHe perdido la línea.\n\n843\n00:50:06.440 --> 00:50:09.440  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n[Francisco] Hemos revisado todos\nlos circuitos. Tiene que haber señal.\n\n844\n00:50:09.600 --> 00:50:10.840  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[Sara] Algo está haciendo mal.\n\n845\n00:50:12.600 --> 00:50:13.880  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[Alba] No hay señal.\n\n846\n00:50:14.040 --> 00:50:16.880  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n- [Alba] No hay señal.\n- Clavija uno, clavija...\n\n847\n00:50:17.040 --> 00:50:18.160  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[Ángeles] Está apagada.\n\n848\n00:50:38.240 --> 00:50:39.560  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n[en inglés] ¿Hola?\n\n849\n00:50:40.320 --> 00:50:41.960  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n¿Washington DC?\n\n850\n00:50:51.160 --> 00:50:54.160  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n<i>Un día para la historia,</i>\n<i>el triunfo de las comunicaciones.</i>\n\n851\n00:50:56.240 --> 00:50:58.840  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n<i>El mundo en manos de una mujer:</i>\n<i>una telefonista.</i>\n\n852\n00:50:59.000 --> 00:51:01.480  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n[Alfonso XIII en inglés] Gracias.\nMuchas gracias, señor...\n\n853\n00:51:01.640 --> 00:51:03.400  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>Todos celebraban ese hecho insólito</i>\n\n854\n00:51:03.560 --> 00:51:05.360  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>sintiéndose parte de un nuevo mundo.</i>\n\n855\n00:51:05.520 --> 00:51:07.760  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>Aunque algunas ya empezaban a comprender</i>\n\n856\n00:51:07.920 --> 00:51:09.920  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>que ese nuevo mundo no era tan idílico</i>\n\n857\n00:51:10.080 --> 00:51:12.360  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>ni tan sencillo como habrían deseado.</i>\n\n858\n00:51:12.520 --> 00:51:16.800  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n<i>Que implicaría</i>\n<i>renuncias familiares, soledad...</i>\n\n859\n00:51:17.720 --> 00:51:20.560  position:50.00%,middle  align:middle size:80.00%  line:79.33% \n<i>Porque la independencia</i>\n<i>siempre tiene un precio.</i>\n\n860\n00:51:22.760 --> 00:51:25.360  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>El de Gimena fue su vida, y el mío...</i>\n\n861\n00:51:26.400 --> 00:51:28.400  position:50.00%,middle  align:middle size:80.00%  line:84.67% \n<i>estar condenada a romper las normas.</i>\n\n862\n00:52:03.000 --> 00:52:04.160  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nDetente.\n\n863\n00:52:14.720 --> 00:52:16.000  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nSé quién eres.\n\n864\n00:52:23.520 --> 00:52:25.840  position:50.00%,middle  align:middle size:80.00%  line:79.33% \nDiez años no son suficientes\npara olvidarte...\n\n865\n00:52:27.320 --> 00:52:28.600  position:50.00%,middle  align:middle size:80.00%  line:84.67% \nAlba.\n\n"
  },
  {
    "path": "tests/samples/no_captions.vtt",
    "content": "WEBVTT"
  },
  {
    "path": "tests/samples/one_caption.srt",
    "content": "1\n00:00:00,500 --> 00:00:07,000\nCaption text #1"
  },
  {
    "path": "tests/samples/one_caption.vtt",
    "content": "WEBVTT\n\n00:00:00.500 --> 00:00:07.000\nCaption text #1"
  },
  {
    "path": "tests/samples/sample.sbv",
    "content": "0:00:00.378,0:00:11.378\nCaption text #1\n\n0:00:11.378,0:00:12.305\nCaption text #2\n\n0:00:13.489,0:00:15.489\nCaption text #3 (line 1)\nCaption text #3 (line 2)\n\n0:00:15.489,0:00:16.234\nCaption text #4\n\n0:00:17.484,0:00:16.543\nCaption text #5"
  },
  {
    "path": "tests/samples/sample.srt",
    "content": "1\n00:00:00,500 --> 00:00:07,000\nCaption text #1\n\n2\n00:00:07,000 --> 00:00:11,890\nCaption text #2\n\n3\n00:00:11,890 --> 00:00:16,320\nCaption text #3\n\n4\n00:00:16,320 --> 00:00:21,580\nCaption text #4\n\n5\n00:00:21,580 --> 00:00:23,880\nCaption text #5"
  },
  {
    "path": "tests/samples/sample.vtt",
    "content": "WEBVTT\n\n00:00:00.500 --> 00:00:07.000\nCaption text #1\n\n00:00:07.000 --> 00:00:11.890\nCaption text #2\n\n00:00:11.890 --> 00:00:16.320\nCaption text #3\n\n00:00:16.320 --> 00:00:21.580\nCaption text #4\n\n00:00:21.580 --> 00:00:23.880\nCaption text #5\n\n00:00:23.880 --> 00:00:27.280\nCaption text #6\n\n00:00:27.280 --> 00:00:30.280\nCaption text #7\n\n00:00:30.280 --> 00:00:36.510\nCaption text #8\n\n00:00:36.510 --> 00:00:38.870\nCaption text #9\n\n00:00:38.870 --> 00:00:45.000\nCaption text #10\n\n00:00:45.000 --> 00:00:47.000\nCaption text #11\n\n00:00:47.000 --> 00:00:50.970\nCaption text #12\n\n00:00:50.970 --> 00:00:54.440\nCaption text #13\n\n00:00:54.440 --> 00:00:58.600\nCaption text #14\n\n00:00:58.600 --> 00:01:01.350\nCaption text #15\n\n00:01:01.350 --> 00:01:04.300\nCaption text #16"
  },
  {
    "path": "tests/samples/styles.vtt",
    "content": "WEBVTT\n\nSTYLE\n::cue {\n  background-image: linear-gradient(to bottom, dimgray, lightgray);\n  color: papayawhip;\n}\n\nSTYLE\n::cue(b) {\n  color: peachpuff;\n}\n\n00:00:00.000 --> 00:00:10.000\n- Hello <b>world</b>."
  },
  {
    "path": "tests/samples/styles_with_comments.vtt",
    "content": "WEBVTT\n\nNOTE Sample of comments with styles\n\nSTYLE\n::cue {\n  background-image: linear-gradient(to bottom, dimgray, lightgray);\n  color: papayawhip;\n}\n\nNOTE This is the second block of styles\n\nNOTE\nMultiline comment for the same\nsecond block of styles\n\nSTYLE\n::cue(b) {\n  color: peachpuff;\n}\n\n00:00:00.000 --> 00:00:10.000\n- Hello <b>world</b>."
  },
  {
    "path": "tests/samples/two_captions.sbv",
    "content": "0:00:00.378,0:00:11.378\nCaption text #1\n\n0:00:11.378,0:00:12.305\nCaption text #2 (line 1)\nCaption text #2 (line 2)"
  },
  {
    "path": "tests/samples/using_identifiers.vtt",
    "content": "WEBVTT\n\n00:00:00.500 --> 00:00:07.000\nCaption text #1\n\nsecond caption\n00:00:07.000 --> 00:00:11.890\nCaption text #2\n\n00:00:11.890 --> 00:00:16.320\nCaption text #3\n\n4\n00:00:16.320 --> 00:00:21.580\nCaption text #4\n\n00:00:21.580 --> 00:00:23.880\nCaption text #5\n\n00:00:23.880 --> 00:00:27.280\nCaption text #6"
  },
  {
    "path": "tests/samples/youtube_dl.vtt",
    "content": "WEBVTT\nKind: captions\nLanguage: en\nStyle:\n::cue(c.colorCCCCCC) { color: rgb(204,204,204);\n }\n::cue(c.colorE5E5E5) { color: rgb(229,229,229);\n }\n##\n\n\n00:04:46.070 --> 00:04:46.470 align:start position:0%\nyeah\n\n\n00:04:46.470 --> 00:05:04.080 align:start position:0%\nyeah\n<c.colorCCCCCC>what</c>\n00:05:04.080 --> 00:05:05.069 align:start position:0%\nthis<00:05:04.199><c> will</c><c.colorE5E5E5><00:05:04.379><c> happen</c></c><c.colorCCCCCC><00:05:04.620><c> is</c><00:05:04.860><c> I'm</c><00:05:05.069><c> telling</c></c>\n\n00:05:05.069 --> 00:05:05.400 align:start position:0%\nthis will<c.colorE5E5E5> happen</c><c.colorCCCCCC> is I'm telling\n </c>\n"
  },
  {
    "path": "tests/test_cli.py",
    "content": "import unittest\nimport tempfile\nimport os\nimport pathlib\nimport textwrap\n\nfrom webvtt.cli import main\n\n\nclass CLITestCase(unittest.TestCase):\n\n    def test_cli(self):\n        vtt_file = (\n            pathlib.Path(__file__).resolve().parent\n            / 'samples' / 'sample.vtt'\n            )\n\n        with tempfile.TemporaryDirectory() as temp_dir:\n\n            main(['segment', str(vtt_file.resolve()), '-o', temp_dir])\n            _, dirs, files = next(os.walk(temp_dir))\n\n            self.assertEqual(len(dirs), 0)\n            self.assertEqual(len(files), 8)\n            for expected_file in ('prog_index.m3u8',\n                                  'fileSequence0.webvtt',\n                                  'fileSequence1.webvtt',\n                                  'fileSequence2.webvtt',\n                                  'fileSequence3.webvtt',\n                                  'fileSequence4.webvtt',\n                                  'fileSequence5.webvtt',\n                                  'fileSequence6.webvtt',\n                                  ):\n                self.assertIn(expected_file, files)\n\n            self.assertEqual(\n                (pathlib.Path(temp_dir) / 'prog_index.m3u8').read_text(),\n                textwrap.dedent(\n                '''\n                #EXTM3U\n                #EXT-X-TARGETDURATION:10\n                #EXT-X-VERSION:3\n                #EXT-X-PLAYLIST-TYPE:VOD\n                #EXTINF:30.00000\n                fileSequence0.webvtt\n                #EXTINF:30.00000\n                fileSequence1.webvtt\n                #EXTINF:30.00000\n                fileSequence2.webvtt\n                #EXTINF:30.00000\n                fileSequence3.webvtt\n                #EXTINF:30.00000\n                fileSequence4.webvtt\n                #EXTINF:30.00000\n                fileSequence5.webvtt\n                #EXTINF:30.00000\n                fileSequence6.webvtt\n                #EXT-X-ENDLIST\n                '''\n                ).lstrip())\n            self.assertEqual(\n                (pathlib.Path(temp_dir) / 'fileSequence0.webvtt').read_text(),\n                textwrap.dedent(\n                '''\n                WEBVTT\n                X-TIMESTAMP-MAP=MPEGTS:900000,LOCAL:00:00:00.000\n\n                00:00:00.500 --> 00:00:07.000\n                Caption text #1\n\n                00:00:07.000 --> 00:00:11.890\n                Caption text #2\n                '''\n                ).lstrip())\n            self.assertEqual(\n                (pathlib.Path(temp_dir) / 'fileSequence1.webvtt').read_text(),\n                textwrap.dedent(\n                    '''\n                    WEBVTT\n                    X-TIMESTAMP-MAP=MPEGTS:900000,LOCAL:00:00:00.000\n\n                    00:00:07.000 --> 00:00:11.890\n                    Caption text #2\n\n                    00:00:11.890 --> 00:00:16.320\n                    Caption text #3\n\n                    00:00:16.320 --> 00:00:21.580\n                    Caption text #4\n                    '''\n                ).lstrip())\n            self.assertEqual(\n                (pathlib.Path(temp_dir) / 'fileSequence2.webvtt').read_text(),\n                textwrap.dedent(\n                    '''\n                    WEBVTT\n                    X-TIMESTAMP-MAP=MPEGTS:900000,LOCAL:00:00:00.000\n\n                    00:00:16.320 --> 00:00:21.580\n                    Caption text #4\n\n                    00:00:21.580 --> 00:00:23.880\n                    Caption text #5\n\n                    00:00:23.880 --> 00:00:27.280\n                    Caption text #6\n\n                    00:00:27.280 --> 00:00:30.280\n                    Caption text #7\n                    '''\n                ).lstrip())\n            self.assertEqual(\n                (pathlib.Path(temp_dir) / 'fileSequence3.webvtt').read_text(),\n                textwrap.dedent(\n                    '''\n                    WEBVTT\n                    X-TIMESTAMP-MAP=MPEGTS:900000,LOCAL:00:00:00.000\n\n                    00:00:27.280 --> 00:00:30.280\n                    Caption text #7\n\n                    00:00:30.280 --> 00:00:36.510\n                    Caption text #8\n\n                    00:00:36.510 --> 00:00:38.870\n                    Caption text #9\n\n                    00:00:38.870 --> 00:00:45.000\n                    Caption text #10\n                    '''\n                ).lstrip())\n            self.assertEqual(\n                (pathlib.Path(temp_dir) / 'fileSequence4.webvtt').read_text(),\n                textwrap.dedent(\n                    '''\n                    WEBVTT\n                    X-TIMESTAMP-MAP=MPEGTS:900000,LOCAL:00:00:00.000\n\n                    00:00:38.870 --> 00:00:45.000\n                    Caption text #10\n\n                    00:00:45.000 --> 00:00:47.000\n                    Caption text #11\n\n                    00:00:47.000 --> 00:00:50.970\n                    Caption text #12\n                    '''\n                ).lstrip())\n            self.assertEqual(\n                (pathlib.Path(temp_dir) / 'fileSequence5.webvtt').read_text(),\n                textwrap.dedent(\n                    '''\n                    WEBVTT\n                    X-TIMESTAMP-MAP=MPEGTS:900000,LOCAL:00:00:00.000\n\n                    00:00:47.000 --> 00:00:50.970\n                    Caption text #12\n\n                    00:00:50.970 --> 00:00:54.440\n                    Caption text #13\n\n                    00:00:54.440 --> 00:00:58.600\n                    Caption text #14\n\n                    00:00:58.600 --> 00:01:01.350\n                    Caption text #15\n                    '''\n                ).lstrip())\n            self.assertEqual(\n                (pathlib.Path(temp_dir) / 'fileSequence6.webvtt').read_text(),\n                textwrap.dedent(\n                    '''\n                    WEBVTT\n                    X-TIMESTAMP-MAP=MPEGTS:900000,LOCAL:00:00:00.000\n\n                    00:00:58.600 --> 00:01:01.350\n                    Caption text #15\n\n                    00:01:01.350 --> 00:01:04.300\n                    Caption text #16\n                    '''\n                ).lstrip())\n"
  },
  {
    "path": "tests/test_models.py",
    "content": "import unittest\n\nfrom webvtt.models import Timestamp, Caption, Style\nfrom webvtt.errors import MalformedCaptionError\n\n\nclass TestTimestamp(unittest.TestCase):\n\n    def test_instantiation(self):\n        timestamp = Timestamp(\n            hours=1, minutes=12, seconds=23, milliseconds=500\n            )\n        self.assertEqual(timestamp.hours, 1)\n        self.assertEqual(timestamp.minutes, 12)\n        self.assertEqual(timestamp.seconds, 23)\n        self.assertEqual(timestamp.milliseconds, 500)\n\n    def test_from_string(self):\n        timestamp = Timestamp.from_string('01:24:11.670')\n        self.assertEqual(timestamp.hours, 1)\n        self.assertEqual(timestamp.minutes, 24)\n        self.assertEqual(timestamp.seconds, 11)\n        self.assertEqual(timestamp.milliseconds, 670)\n\n    def test_from_string_single_digits(self):\n        timestamp = Timestamp.from_string('1:2:7.670')\n        self.assertEqual(timestamp.hours, 1)\n        self.assertEqual(timestamp.minutes, 2)\n        self.assertEqual(timestamp.seconds, 7)\n        self.assertEqual(timestamp.milliseconds, 670)\n\n    def test_from_string_missing_hours(self):\n        timestamp = Timestamp.from_string('24:11.670')\n        self.assertEqual(timestamp.hours, 0)\n        self.assertEqual(timestamp.minutes, 24)\n        self.assertEqual(timestamp.seconds, 11)\n        self.assertEqual(timestamp.milliseconds, 670)\n\n    def test_from_string_wrong_minutes(self):\n        with self.assertRaises(MalformedCaptionError):\n            Timestamp.from_string('01:76:11.670')\n\n    def test_from_string_wrong_seconds(self):\n        with self.assertRaises(MalformedCaptionError):\n            Timestamp.from_string('01:24:87.670')\n\n    def test_from_string_wrong_type(self):\n        with self.assertRaises(MalformedCaptionError):\n            Timestamp.from_string(1234)\n\n    def test_from_string_wrong_value(self):\n        with self.assertRaises(MalformedCaptionError):\n            Timestamp.from_string('01:24:11:670')\n\n    def test_to_tuple(self):\n        self.assertEqual(\n            Timestamp(\n                hours=1, minutes=12, seconds=23, milliseconds=500\n                ).to_tuple(),\n            (1, 12, 23, 500)\n            )\n\n    def test_equality(self):\n        self.assertTrue(\n            Timestamp(\n                hours=1, minutes=12, seconds=23, milliseconds=500\n                ) ==\n            Timestamp.from_string('01:12:23.500')\n            )\n\n    def test_not_equality(self):\n        self.assertTrue(\n            Timestamp(\n                hours=1, minutes=12, seconds=23, milliseconds=500\n                ) !=\n            Timestamp.from_string('01:12:23.600')\n            )\n\n    def test_greater_than(self):\n        self.assertTrue(\n            Timestamp(\n                hours=1, minutes=12, seconds=23, milliseconds=600\n                ) >\n            Timestamp.from_string('01:12:23.500')\n            )\n\n    def test_less_than(self):\n        self.assertTrue(\n            Timestamp(\n                hours=1, minutes=12, seconds=23, milliseconds=500\n                ) <\n            Timestamp.from_string('01:12:23.600')\n            )\n\n    def test_greater_or_equal_than(self):\n        self.assertTrue(\n            Timestamp(\n                hours=1, minutes=12, seconds=23, milliseconds=500\n                ) >=\n            Timestamp.from_string('01:12:23.500')\n            )\n        self.assertTrue(\n            Timestamp(\n                hours=1, minutes=12, seconds=23, milliseconds=600\n                ) >=\n            Timestamp.from_string('01:12:23.500')\n            )\n\n    def test_less_or_equal_than(self):\n        self.assertTrue(\n            Timestamp(\n                hours=1, minutes=12, seconds=23, milliseconds=500\n                ) <=\n            Timestamp.from_string('01:12:23.500')\n            )\n        self.assertTrue(\n            Timestamp(\n                hours=1, minutes=12, seconds=23, milliseconds=500\n                ) <=\n            Timestamp.from_string('01:12:23.600')\n            )\n\n    def test_repr(self):\n        timestamp = Timestamp(\n            hours=1,\n            minutes=12,\n            seconds=45,\n            milliseconds=320\n            )\n\n        self.assertEqual(\n            repr(timestamp),\n            '<Timestamp hours=1 minutes=12 seconds=45 milliseconds=320>'\n            )\n\n\nclass TestCaption(unittest.TestCase):\n\n    def test_instantiation(self):\n        caption = Caption(\n            start='00:00:07.000',\n            end='00:00:11.890',\n            text='Hello test!',\n            identifier='A test caption'\n            )\n        self.assertEqual(caption.start, '00:00:07.000')\n        self.assertEqual(caption.end, '00:00:11.890')\n        self.assertEqual(caption.text, 'Hello test!')\n        self.assertEqual(caption.identifier, 'A test caption')\n\n    def test_timestamp_wrong_type(self):\n        with self.assertRaises(MalformedCaptionError):\n            Caption(\n                start=1234,\n                end='00:00:11.890',\n                text='Hello test!',\n                identifier='A test caption'\n                )\n\n    def test_identifier_is_optional(self):\n        caption = Caption(\n            start='00:00:07.000',\n            end='00:00:11.890',\n            text='Hello test!',\n            )\n        self.assertIsNone(caption.identifier)\n\n    def test_multi_lines(self):\n        caption = Caption(\n            start='00:00:07.000',\n            end='00:00:11.890',\n            text='Hello test!\\nThis is the second line',\n            identifier='A test caption'\n            )\n        self.assertEqual(caption.text, 'Hello test!\\nThis is the second line')\n        self.assertListEqual(\n            caption.lines,\n            ['Hello test!', 'This is the second line']\n            )\n\n    def test_multi_lines_accepts_list(self):\n        caption = Caption(\n            start='00:00:07.000',\n            end='00:00:11.890',\n            text=['Hello test!', 'This is the second line'],\n            identifier='A test caption'\n            )\n        self.assertEqual(caption.text, 'Hello test!\\nThis is the second line')\n        self.assertListEqual(\n            caption.lines,\n            ['Hello test!', 'This is the second line']\n            )\n\n    def test_cuetags(self):\n        caption = Caption(\n            start='00:00:07.000',\n            end='00:00:11.890',\n            text=[\n                'Hello <c.colorE5E5E5>test</c>!',\n                'This is the <c.colorE5E5E5>second</c> line'\n                ],\n            identifier='A test caption'\n            )\n        self.assertEqual(caption.text, 'Hello test!\\nThis is the second line')\n        self.assertEqual(\n            caption.raw_text,\n            'Hello <c.colorE5E5E5>test</c>!\\n'\n            'This is the <c.colorE5E5E5>second</c> line'\n            )\n\n    def test_in_seconds(self):\n        caption = Caption(\n            start='00:00:07.000',\n            end='00:00:11.890',\n            text=['Hello test!', 'This is the second line'],\n            identifier='A test caption'\n            )\n        self.assertEqual(caption.start_in_seconds, 7)\n        self.assertEqual(caption.end_in_seconds, 11)\n\n    def test_wrong_start_timestamp(self):\n        self.assertRaises(\n            MalformedCaptionError,\n            Caption,\n            start='1234',\n            end='00:00:11.890',\n            text='Hello Test!'\n            )\n\n    def test_wrong_type_start_timestamp(self):\n        self.assertRaises(\n            MalformedCaptionError,\n            Caption,\n            start=1234,\n            end='00:00:11.890',\n            text='Hello Test!'\n            )\n\n    def test_wrong_end_timestamp(self):\n        self.assertRaises(\n            MalformedCaptionError,\n            Caption,\n            start='00:00:07.000',\n            end='1234',\n            text='Hello Test!'\n            )\n\n    def test_wrong_type_end_timestamp(self):\n        self.assertRaises(\n            MalformedCaptionError,\n            Caption,\n            start='00:00:07.000',\n            end=1234,\n            text='Hello Test!'\n            )\n\n    def test_equality(self):\n        caption1 = Caption(\n            start='00:00:07.000',\n            end='00:00:11.890',\n            text='Hello test!',\n            identifier='A test caption'\n            )\n\n        caption2 = Caption(\n            start='00:00:07.000',\n            end='00:00:11.890',\n            text='Hello test!',\n            identifier='A test caption'\n            )\n\n        self.assertTrue(caption1 == caption2)\n\n        caption1 = Caption(\n            start='00:00:02.000',\n            end='00:00:11.890',\n            text='Hello test!',\n            identifier='A test caption'\n            )\n\n        caption2 = Caption(\n            start='00:00:07.000',\n            end='00:00:11.890',\n            text='Hello test!',\n            identifier='A test caption'\n            )\n\n        self.assertFalse(caption1 == caption2)\n\n        self.assertFalse(\n            Caption(\n                start='00:00:07.000',\n                end='00:00:11.890',\n                text='Hello test!',\n                identifier='A test caption'\n                ) == 1234\n            )\n\n    def test_repr(self):\n        caption = Caption(\n            start='00:00:07.000',\n            end='00:00:11.890',\n            text='Hello test!',\n            identifier='A test caption'\n            )\n\n        self.assertEqual(\n            repr(caption),\n            \"<Caption start='00:00:07.000' end='00:00:11.890' \"\n            \"text='Hello test!' identifier='A test caption'>\"\n            )\n\n    def test_str(self):\n        caption = Caption(\n            start='00:00:07.000',\n            end='00:00:11.890',\n            text='Hello test!',\n            identifier='A test caption'\n            )\n\n        self.assertEqual(\n            str(caption),\n            '00:00:07.000 00:00:11.890 Hello test!'\n            )\n\n    def test_accept_comments(self):\n        caption = Caption(\n            start='00:00:07.000',\n            end='00:00:11.890',\n            text='Hello test!',\n            identifier='A test caption'\n            )\n        caption.comments.append('One comment')\n        caption.comments.append('Another comment')\n\n        self.assertListEqual(\n            caption.comments,\n            ['One comment', 'Another comment']\n            )\n\n    def test_timestamp_update(self):\n        c = Caption('00:00:00.500', '00:00:07.000')\n        c.start = '00:00:01.750'\n        c.end = '00:00:08.250'\n\n        self.assertEqual(c.start, '00:00:01.750')\n        self.assertEqual(c.end, '00:00:08.250')\n\n    def test_timestamp_format(self):\n        c = Caption('01:02:03.400', '02:03:04.500')\n        self.assertEqual(c.start, '01:02:03.400')\n        self.assertEqual(c.end, '02:03:04.500')\n\n        c = Caption('02:03.400', '03:04.500')\n        self.assertEqual(c.start, '00:02:03.400')\n        self.assertEqual(c.end, '00:03:04.500')\n\n    def test_update_text(self):\n        c = Caption(text='Caption line #1')\n        c.text = 'Caption line #1 updated'\n        self.assertEqual(\n            c.text,\n            'Caption line #1 updated'\n            )\n\n    def test_update_text_multiline(self):\n        c = Caption(text='Caption line #1')\n        c.text = 'Caption line #1\\nCaption line #2'\n\n        self.assertEqual(\n            len(c.lines),\n            2\n            )\n\n        self.assertEqual(\n            c.text,\n            'Caption line #1\\nCaption line #2'\n            )\n\n    def test_update_text_wrong_type(self):\n        c = Caption(text='Caption line #1')\n\n        self.assertRaises(\n            AttributeError,\n            setattr,\n            c,\n            'text',\n            123\n            )\n\n    def test_manipulate_lines(self):\n        c = Caption(text=['Caption line #1', 'Caption line #2'])\n        c.lines[0] = 'Caption line #1 updated'\n        self.assertEqual(\n            c.lines[0],\n            'Caption line #1 updated'\n            )\n\n    def test_malformed_start_timestamp(self):\n        self.assertRaises(\n            MalformedCaptionError,\n            Caption,\n            '01:00'\n            )\n\n    def test_voice_span(self):\n        caption = Caption(text='<v Homer Simpson>Hello there!</v>')\n        self.assertEqual(caption.text, 'Hello there!')\n        self.assertEqual(caption.raw_text, '<v Homer Simpson>Hello there!</v>')\n        self.assertEqual(caption.voice, 'Homer Simpson')\n\n    def test_voice_span_with_classes(self):\n        caption = Caption(text='<v.quiet.slow Lisa Simpson>I am Lisa</v>')\n        self.assertEqual(caption.text, 'I am Lisa')\n        self.assertEqual(\n            caption.raw_text,\n            '<v.quiet.slow Lisa Simpson>I am Lisa</v>'\n            )\n        self.assertEqual(caption.voice, 'Lisa Simpson')\n\n    def test_voice_span_is_invalid(self):\n        caption = Caption(text='<v Lets eat donuts')\n        self.assertEqual(caption.text, '<v Lets eat donuts')\n        self.assertEqual(\n            caption.raw_text,\n            '<v Lets eat donuts'\n            )\n        self.assertIsNone(caption.voice)\n\n    def test_voice_span_injected(self):\n        caption = Caption(text='This is a test')\n        self.assertEqual(caption.text, 'This is a test')\n        self.assertEqual(caption.raw_text, 'This is a test')\n        self.assertIsNone(caption.voice)\n        caption.text = '<v Homer Simpson>I like tests</v>'\n        self.assertEqual(caption.text, 'I like tests')\n        self.assertEqual(caption.raw_text, '<v Homer Simpson>I like tests</v>')\n        self.assertEqual(caption.voice, 'Homer Simpson')\n\n    def test_voice_span_removed(self):\n        caption = Caption(text='<v Homer Simpson>I like tests</v>')\n        self.assertEqual(caption.text, 'I like tests')\n        self.assertEqual(caption.raw_text, '<v Homer Simpson>I like tests</v>')\n        self.assertEqual(caption.voice, 'Homer Simpson')\n        caption.text = 'This is a test'\n        self.assertEqual(caption.text, 'This is a test')\n        self.assertEqual(caption.raw_text, 'This is a test')\n        self.assertIsNone(caption.voice)\n\n\nclass TestStyle(unittest.TestCase):\n\n    def test_instantiation(self):\n        style = Style(text='::cue(b) {\\ncolor: peachpuff;\\n}')\n        self.assertEqual(style.text, '::cue(b) {\\ncolor: peachpuff;\\n}')\n        self.assertListEqual(\n            style.lines,\n            ['::cue(b) {', 'color: peachpuff;', '}']\n            )\n\n    def test_text_accept_list_of_strings(self):\n        style = Style(text=['::cue(b) {', 'color: peachpuff;', '}'])\n        self.assertEqual(style.text, '::cue(b) {\\ncolor: peachpuff;\\n}')\n        self.assertListEqual(\n            style.lines,\n            ['::cue(b) {', 'color: peachpuff;', '}']\n            )\n\n    def test_accept_comments(self):\n        style = Style(text='::cue(b) {\\ncolor: peachpuff;\\n}')\n        style.comments.append('One comment')\n        style.comments.append('Another comment')\n\n        self.assertListEqual(\n            style.comments,\n            ['One comment', 'Another comment']\n            )\n\n    def test_get_text(self):\n        style = Style(['::cue(b) {', '  color: peachpuff;', '}'])\n        self.assertEqual(\n            style.text,\n            '::cue(b) {\\n  color: peachpuff;\\n}'\n            )\n"
  },
  {
    "path": "tests/test_sbv.py",
    "content": "import unittest\nimport textwrap\n\nfrom webvtt import sbv\nfrom webvtt.errors import MalformedFileError\nfrom webvtt.models import Caption\n\n\nclass TestSBVCueBlock(unittest.TestCase):\n\n    def test_is_valid(self):\n        self.assertTrue(sbv.SBVCueBlock.is_valid(textwrap.dedent('''\n            00:00:00.500,00:00:07.000\n            Caption #1\n            ''').strip().split('\\n'))\n            )\n\n        self.assertTrue(sbv.SBVCueBlock.is_valid(textwrap.dedent('''\n            0:0:0.500,0:0:7.000\n            Caption #1\n            ''').strip().split('\\n'))\n            )\n\n        self.assertTrue(sbv.SBVCueBlock.is_valid(textwrap.dedent('''\n            00:00:00.500,00:00:07.000\n            Caption #1 line 1\n            Caption #1 line 2\n            ''').strip().split('\\n'))\n            )\n\n        self.assertFalse(sbv.SBVCueBlock.is_valid(textwrap.dedent('''\n            00:00:00.500 --> 00:00:07.000\n            Caption #1\n            ''').strip().split('\\n'))\n            )\n\n        self.assertFalse(sbv.SBVCueBlock.is_valid(textwrap.dedent('''\n            1\n            00:00:00.500,00:00:07.000\n            Caption #1\n            ''').strip().split('\\n'))\n            )\n\n        self.assertFalse(sbv.SBVCueBlock.is_valid(textwrap.dedent('''\n            1\n            00:00:00.500,00:00:07.000\n            ''').strip().split('\\n'))\n            )\n\n        self.assertFalse(sbv.SBVCueBlock.is_valid(textwrap.dedent('''\n            1\n            Caption #1\n            ''').strip().split('\\n'))\n            )\n\n        self.assertFalse(sbv.SBVCueBlock.is_valid(textwrap.dedent('''\n            Caption #1\n            ''').strip().split('\\n'))\n            )\n\n        self.assertFalse(sbv.SBVCueBlock.is_valid(textwrap.dedent('''\n            00:00:00.500,00:00:07.000\n            ''').strip().split('\\n'))\n            )\n\n    def test_from_lines(self):\n        cue_block = sbv.SBVCueBlock.from_lines(textwrap.dedent('''\n                    00:00:00.500,00:00:07.000\n                    Caption #1 line 1\n                    Caption #1 line 2\n                    ''').strip().split('\\n')\n                    )\n        self.assertEqual(\n            cue_block.start,\n            '00:00:00.500'\n            )\n        self.assertEqual(\n            cue_block.end,\n            '00:00:07.000'\n            )\n        self.assertEqual(\n            cue_block.payload,\n            ['Caption #1 line 1', 'Caption #1 line 2']\n            )\n\n    def test_from_lines_shorter_timestamps(self):\n        cue_block = sbv.SBVCueBlock.from_lines(textwrap.dedent('''\n                    0:1:2.500,0:1:03.800\n                    Caption #1 line 1\n                    Caption #1 line 2\n                    ''').strip().split('\\n')\n                    )\n        self.assertEqual(\n            cue_block.start,\n            '0:1:2.500'\n            )\n        self.assertEqual(\n            cue_block.end,\n            '0:1:03.800'\n            )\n\n\nclass TestSBVModule(unittest.TestCase):\n\n    def test_parse_invalid_format(self):\n        self.assertRaises(\n            MalformedFileError,\n            sbv.parse,\n            textwrap.dedent('''\n                1\n                00:00:00.500,00:00:07.000\n                Caption text #1\n\n                00:00:07.000,00:00:11.890\n                Caption text #2\n                ''').strip().split('\\n')\n                )\n\n    def test_parse_captions(self):\n        captions = sbv.parse(\n            textwrap.dedent('''\n            00:00:00.500,00:00:07.000\n            Caption #1\n\n            00:00:07.000,00:00:11.890\n            Caption #2 line 1\n            Caption #2 line 2\n            ''').strip().split('\\n')\n            )\n        self.assertEqual(len(captions), 2)\n        self.assertIsInstance(captions[0], Caption)\n        self.assertIsInstance(captions[1], Caption)\n        self.assertEqual(\n            str(captions[0]),\n            '00:00:00.500 00:00:07.000 Caption #1'\n            )\n        self.assertEqual(\n            str(captions[1]),\n            r'00:00:07.000 00:00:11.890 Caption #2 line 1\\n'\n            'Caption #2 line 2'\n            )\n"
  },
  {
    "path": "tests/test_segmenter.py",
    "content": "import os\nimport unittest\nimport tempfile\nimport pathlib\nimport textwrap\n\nfrom webvtt import segmenter\n\nPATH_TO_SAMPLES = pathlib.Path(__file__).resolve().parent / 'samples'\n\n\nclass TestSegmenter(unittest.TestCase):\n\n    def setUp(self):\n        self.temp_dir = tempfile.TemporaryDirectory()\n\n    def tearDown(self):\n        self.temp_dir.cleanup()\n\n    def test_segmentation_with_defaults(self):\n        segmenter.segment(PATH_TO_SAMPLES / 'sample.vtt', self.temp_dir.name)\n\n        _, dirs, files = next(os.walk(self.temp_dir.name))\n\n        self.assertEqual(len(dirs), 0)\n        self.assertEqual(len(files), 8)\n\n        for expected_file in ('prog_index.m3u8',\n                              'fileSequence0.webvtt',\n                              'fileSequence1.webvtt',\n                              'fileSequence2.webvtt',\n                              'fileSequence3.webvtt',\n                              'fileSequence4.webvtt',\n                              'fileSequence5.webvtt',\n                              'fileSequence6.webvtt',\n                              ):\n            self.assertIn(expected_file, files)\n\n        output_path = pathlib.Path(self.temp_dir.name)\n\n        self.assertEqual(\n            (output_path / 'prog_index.m3u8').read_text(),\n            textwrap.dedent(\n                '''\n                #EXTM3U\n                #EXT-X-TARGETDURATION:10\n                #EXT-X-VERSION:3\n                #EXT-X-PLAYLIST-TYPE:VOD\n                #EXTINF:30.00000\n                fileSequence0.webvtt\n                #EXTINF:30.00000\n                fileSequence1.webvtt\n                #EXTINF:30.00000\n                fileSequence2.webvtt\n                #EXTINF:30.00000\n                fileSequence3.webvtt\n                #EXTINF:30.00000\n                fileSequence4.webvtt\n                #EXTINF:30.00000\n                fileSequence5.webvtt\n                #EXTINF:30.00000\n                fileSequence6.webvtt\n                #EXT-X-ENDLIST\n                '''\n                ).lstrip()\n            )\n        self.assertEqual(\n            (output_path / 'fileSequence0.webvtt').read_text(),\n            textwrap.dedent(\n                '''\n                WEBVTT\n                X-TIMESTAMP-MAP=MPEGTS:900000,LOCAL:00:00:00.000\n\n                00:00:00.500 --> 00:00:07.000\n                Caption text #1\n\n                00:00:07.000 --> 00:00:11.890\n                Caption text #2\n                '''\n                ).lstrip()\n            )\n        self.assertEqual(\n            (output_path / 'fileSequence1.webvtt').read_text(),\n            textwrap.dedent(\n                '''\n                WEBVTT\n                X-TIMESTAMP-MAP=MPEGTS:900000,LOCAL:00:00:00.000\n\n                00:00:07.000 --> 00:00:11.890\n                Caption text #2\n\n                00:00:11.890 --> 00:00:16.320\n                Caption text #3\n\n                00:00:16.320 --> 00:00:21.580\n                Caption text #4\n                '''\n                ).lstrip()\n            )\n        self.assertEqual(\n            (output_path / 'fileSequence2.webvtt').read_text(),\n            textwrap.dedent(\n                '''\n                WEBVTT\n                X-TIMESTAMP-MAP=MPEGTS:900000,LOCAL:00:00:00.000\n\n                00:00:16.320 --> 00:00:21.580\n                Caption text #4\n\n                00:00:21.580 --> 00:00:23.880\n                Caption text #5\n\n                00:00:23.880 --> 00:00:27.280\n                Caption text #6\n\n                00:00:27.280 --> 00:00:30.280\n                Caption text #7\n                '''\n                ).lstrip()\n            )\n        self.assertEqual(\n            (output_path / 'fileSequence3.webvtt').read_text(),\n            textwrap.dedent(\n                '''\n                WEBVTT\n                X-TIMESTAMP-MAP=MPEGTS:900000,LOCAL:00:00:00.000\n\n                00:00:27.280 --> 00:00:30.280\n                Caption text #7\n\n                00:00:30.280 --> 00:00:36.510\n                Caption text #8\n\n                00:00:36.510 --> 00:00:38.870\n                Caption text #9\n\n                00:00:38.870 --> 00:00:45.000\n                Caption text #10\n                '''\n                ).lstrip()\n            )\n        self.assertEqual(\n            (output_path / 'fileSequence4.webvtt').read_text(),\n            textwrap.dedent(\n                '''\n                WEBVTT\n                X-TIMESTAMP-MAP=MPEGTS:900000,LOCAL:00:00:00.000\n\n                00:00:38.870 --> 00:00:45.000\n                Caption text #10\n\n                00:00:45.000 --> 00:00:47.000\n                Caption text #11\n\n                00:00:47.000 --> 00:00:50.970\n                Caption text #12\n                '''\n                ).lstrip()\n            )\n        self.assertEqual(\n            (output_path / 'fileSequence5.webvtt').read_text(),\n            textwrap.dedent(\n                '''\n                WEBVTT\n                X-TIMESTAMP-MAP=MPEGTS:900000,LOCAL:00:00:00.000\n\n                00:00:47.000 --> 00:00:50.970\n                Caption text #12\n\n                00:00:50.970 --> 00:00:54.440\n                Caption text #13\n\n                00:00:54.440 --> 00:00:58.600\n                Caption text #14\n\n                00:00:58.600 --> 00:01:01.350\n                Caption text #15\n                '''\n                ).lstrip()\n            )\n        self.assertEqual(\n            (output_path / 'fileSequence6.webvtt').read_text(),\n            textwrap.dedent(\n                '''\n                WEBVTT\n                X-TIMESTAMP-MAP=MPEGTS:900000,LOCAL:00:00:00.000\n\n                00:00:58.600 --> 00:01:01.350\n                Caption text #15\n\n                00:01:01.350 --> 00:01:04.300\n                Caption text #16\n                '''\n                ).lstrip()\n            )\n\n    def test_segmentation_with_custom_values(self):\n        segmenter.segment(\n            webvtt_path=PATH_TO_SAMPLES / 'sample.vtt',\n            output=self.temp_dir.name,\n            seconds=30,\n            mpegts=800000\n            )\n\n        _, dirs, files = next(os.walk(self.temp_dir.name))\n\n        self.assertEqual(len(dirs), 0)\n        self.assertEqual(len(files), 4)\n\n        for expected_file in ('prog_index.m3u8',\n                              'fileSequence0.webvtt',\n                              'fileSequence1.webvtt',\n                              'fileSequence2.webvtt',\n                              ):\n            self.assertIn(expected_file, files)\n\n        output_path = pathlib.Path(self.temp_dir.name)\n\n        self.assertEqual(\n            (output_path / 'prog_index.m3u8').read_text(),\n            textwrap.dedent(\n                '''\n                #EXTM3U\n                #EXT-X-TARGETDURATION:30\n                #EXT-X-VERSION:3\n                #EXT-X-PLAYLIST-TYPE:VOD\n                #EXTINF:30.00000\n                fileSequence0.webvtt\n                #EXTINF:30.00000\n                fileSequence1.webvtt\n                #EXTINF:30.00000\n                fileSequence2.webvtt\n                #EXT-X-ENDLIST\n                '''\n                ).lstrip()\n            )\n        self.assertEqual(\n            (output_path / 'fileSequence0.webvtt').read_text(),\n            textwrap.dedent(\n                '''\n                WEBVTT\n                X-TIMESTAMP-MAP=MPEGTS:800000,LOCAL:00:00:00.000\n\n                00:00:00.500 --> 00:00:07.000\n                Caption text #1\n\n                00:00:07.000 --> 00:00:11.890\n                Caption text #2\n\n                00:00:11.890 --> 00:00:16.320\n                Caption text #3\n\n                00:00:16.320 --> 00:00:21.580\n                Caption text #4\n\n                00:00:21.580 --> 00:00:23.880\n                Caption text #5\n\n                00:00:23.880 --> 00:00:27.280\n                Caption text #6\n\n                00:00:27.280 --> 00:00:30.280\n                Caption text #7\n                '''\n                ).lstrip()\n            )\n        self.assertEqual(\n            (output_path / 'fileSequence1.webvtt').read_text(),\n            textwrap.dedent(\n                '''\n                WEBVTT\n                X-TIMESTAMP-MAP=MPEGTS:800000,LOCAL:00:00:00.000\n\n                00:00:27.280 --> 00:00:30.280\n                Caption text #7\n\n                00:00:30.280 --> 00:00:36.510\n                Caption text #8\n\n                00:00:36.510 --> 00:00:38.870\n                Caption text #9\n\n                00:00:38.870 --> 00:00:45.000\n                Caption text #10\n\n                00:00:45.000 --> 00:00:47.000\n                Caption text #11\n\n                00:00:47.000 --> 00:00:50.970\n                Caption text #12\n\n                00:00:50.970 --> 00:00:54.440\n                Caption text #13\n\n                00:00:54.440 --> 00:00:58.600\n                Caption text #14\n\n                00:00:58.600 --> 00:01:01.350\n                Caption text #15\n                '''\n                ).lstrip()\n            )\n        self.assertEqual(\n            (output_path / 'fileSequence2.webvtt').read_text(),\n            textwrap.dedent(\n                '''\n                WEBVTT\n                X-TIMESTAMP-MAP=MPEGTS:800000,LOCAL:00:00:00.000\n\n                00:00:58.600 --> 00:01:01.350\n                Caption text #15\n\n                00:01:01.350 --> 00:01:04.300\n                Caption text #16\n                '''\n                ).lstrip()\n            )\n\n    def test_segment_with_no_captions(self):\n        segmenter.segment(\n            webvtt_path=PATH_TO_SAMPLES / 'no_captions.vtt',\n            output=self.temp_dir.name\n            )\n\n        _, dirs, files = next(os.walk(self.temp_dir.name))\n\n        self.assertEqual(len(dirs), 0)\n        self.assertEqual(len(files), 1)\n        self.assertIn('prog_index.m3u8', files)\n\n        self.assertEqual(\n            (pathlib.Path(self.temp_dir.name) / 'prog_index.m3u8').read_text(),\n            textwrap.dedent(\n                '''\n                #EXTM3U\n                #EXT-X-TARGETDURATION:10\n                #EXT-X-VERSION:3\n                #EXT-X-PLAYLIST-TYPE:VOD\n                #EXT-X-ENDLIST\n                '''\n                ).lstrip()\n            )\n"
  },
  {
    "path": "tests/test_srt.py",
    "content": "import unittest\nimport io\nimport textwrap\n\nfrom webvtt import srt\nfrom webvtt.errors import MalformedFileError\nfrom webvtt.models import Caption\n\n\nclass TestSRTCueBlock(unittest.TestCase):\n\n    def test_is_valid(self):\n        self.assertTrue(srt.SRTCueBlock.is_valid(textwrap.dedent('''\n            1\n            00:00:00,500 --> 00:00:07,000\n            Caption #1\n            ''').strip().split('\\n'))\n            )\n\n        self.assertTrue(srt.SRTCueBlock.is_valid(textwrap.dedent('''\n            1\n            00:00:00,500 --> 00:00:07,000\n            Caption #1 line 1\n            Caption #1 line 2\n            ''').strip().split('\\n'))\n            )\n\n        self.assertFalse(srt.SRTCueBlock.is_valid(textwrap.dedent('''\n            00:00:00,500 --> 00:00:07,000\n            Caption #1\n            ''').strip().split('\\n'))\n            )\n\n        self.assertFalse(srt.SRTCueBlock.is_valid(textwrap.dedent('''\n            1\n            00:00:00.500 --> 00:00:07.000\n            Caption #1\n            ''').strip().split('\\n'))\n            )\n\n        self.assertFalse(srt.SRTCueBlock.is_valid(textwrap.dedent('''\n            1\n            00:00:00,500 --> 00:00:07,000\n            ''').strip().split('\\n'))\n            )\n\n        self.assertFalse(srt.SRTCueBlock.is_valid(textwrap.dedent('''\n            1\n            Caption #1\n            ''').strip().split('\\n'))\n            )\n\n        self.assertFalse(srt.SRTCueBlock.is_valid(textwrap.dedent('''\n            Caption #1\n            ''').strip().split('\\n'))\n            )\n\n        self.assertFalse(srt.SRTCueBlock.is_valid(textwrap.dedent('''\n            00:00:00,500 --> 00:00:07,000\n            ''').strip().split('\\n'))\n            )\n\n    def test_from_lines(self):\n        cue_block = srt.SRTCueBlock.from_lines(textwrap.dedent('''\n            1\n            00:00:00,500 --> 00:00:07,000\n            Caption #1 line 1\n            Caption #1 line 2\n            ''').strip().split('\\n')\n            )\n        self.assertEqual(cue_block.index, '1')\n        self.assertEqual(\n            cue_block.start,\n            '00:00:00,500'\n            )\n        self.assertEqual(\n            cue_block.end,\n            '00:00:07,000'\n            )\n        self.assertEqual(\n            cue_block.payload,\n            ['Caption #1 line 1', 'Caption #1 line 2']\n            )\n\n\nclass TestSRTModule(unittest.TestCase):\n\n    def test_parse_invalid_format(self):\n        self.assertRaises(\n            MalformedFileError,\n            srt.parse,\n            textwrap.dedent('''\n                00:00:00,500 --> 00:00:07,000\n                Caption text #1\n\n                00:00:07,000 --> 00:00:11,890\n                Caption text #2\n                ''').strip().split('\\n')\n            )\n\n    def test_parse_captions(self):\n        captions = srt.parse(\n            textwrap.dedent('''\n            1\n            00:00:00,500 --> 00:00:07,000\n            Caption #1\n\n            2\n            00:00:07,000 --> 00:00:11,890\n            Caption #2 line 1\n            Caption #2 line 2\n            ''').strip().split('\\n')\n            )\n        self.assertEqual(len(captions), 2)\n        self.assertIsInstance(captions[0], Caption)\n        self.assertIsInstance(captions[1], Caption)\n        self.assertEqual(\n            str(captions[0]),\n            '00:00:00.500 00:00:07.000 Caption #1'\n            )\n        self.assertEqual(\n            str(captions[1]),\n            r'00:00:07.000 00:00:11.890 Caption #2 line 1\\n'\n            'Caption #2 line 2'\n            )\n\n    def test_write(self):\n        out = io.StringIO()\n        captions = [\n            Caption(start='00:00:00.500',\n                    end='00:00:07.000',\n                    text='Caption #1'\n                    ),\n            Caption(start='00:00:07.000',\n                    end='00:00:11.890',\n                    text=['Caption #2 line 1',\n                          'Caption #2 line 2'\n                          ]\n                    )\n            ]\n        captions[0].comments.append('Comment for the first caption')\n        captions[1].comments.append('Comment for the second caption')\n\n        srt.write(out, captions)\n\n        out.seek(0)\n\n        self.assertEqual(\n            out.read(),\n            textwrap.dedent('''\n                1\n                00:00:00,500 --> 00:00:07,000\n                Caption #1\n\n                2\n                00:00:07,000 --> 00:00:11,890\n                Caption #2 line 1\n                Caption #2 line 2\n            ''').strip()\n            )\n"
  },
  {
    "path": "tests/test_utils.py",
    "content": "import unittest\nimport tempfile\n\nfrom webvtt.utils import FileWrapper, CODEC_BOMS\n\n\nclass TestUtils(unittest.TestCase):\n\n    def test_open_file(self):\n        with tempfile.NamedTemporaryFile('w') as f:\n            f.write('Hello test!')\n            f.flush()\n            with FileWrapper.open(f.name) as fw:\n                self.assertEqual(fw.file.read(), 'Hello test!')\n                self.assertEqual(fw.file.encoding, 'utf-8')\n\n    def test_open_file_with_bom(self):\n        for encoding, bom in CODEC_BOMS.items():\n            with tempfile.NamedTemporaryFile('wb') as f:\n                f.write(bom)\n                f.write('Hello test'.encode(encoding))\n                f.flush()\n\n                with FileWrapper.open(f.name) as fw:\n                    self.assertEqual(fw.file.read(), 'Hello test')\n                    self.assertEqual(fw.file.encoding, encoding)\n"
  },
  {
    "path": "tests/test_vtt.py",
    "content": "import unittest\nimport textwrap\nimport io\n\nfrom webvtt import vtt\nfrom webvtt.errors import MalformedFileError\nfrom webvtt.models import Caption, Style\n\n\nclass TestWebVTTCueBlock(unittest.TestCase):\n\n    def test_is_valid(self):\n        self.assertTrue(\n            vtt.WebVTTCueBlock.is_valid(textwrap.dedent('''\n            00:00:00.500 --> 00:00:07.000\n            Caption #1\n            ''').strip().split('\\n'))\n            )\n\n        self.assertTrue(\n            vtt.WebVTTCueBlock.is_valid(textwrap.dedent('''\n            00:00:00.500 --> 00:00:07.000\n            Caption #1 line 1\n            Caption #1 line 2\n            ''').strip().split('\\n'))\n            )\n\n        self.assertTrue(\n            vtt.WebVTTCueBlock.is_valid(textwrap.dedent('''\n            identifier\n            00:00:00.500 --> 00:00:07.000\n            Caption #1\n            ''').strip().split('\\n'))\n            )\n\n        self.assertTrue(\n            vtt.WebVTTCueBlock.is_valid(textwrap.dedent('''\n            identifier\n            00:00:00.500 --> 00:00:07.000\n            Caption #1 line 1\n            Caption #1 line 2\n            ''').strip().split('\\n'))\n            )\n\n        self.assertFalse(\n            vtt.WebVTTCueBlock.is_valid(textwrap.dedent('''\n            00:00:00.500 00:00:07.000\n            Caption #1 line 1\n            ''').strip().split('\\n'))\n            )\n\n        self.assertFalse(\n            vtt.WebVTTCueBlock.is_valid(textwrap.dedent('''\n            00:00:00.500 --> 00:00:07.000\n            ''').strip().split('\\n'))\n            )\n\n    def test_from_lines(self):\n        cue_block = vtt.WebVTTCueBlock.from_lines(textwrap.dedent('''\n            identifier\n            00:00:00.500 --> 00:00:07.000\n            Caption #1 line 1\n            Caption #1 line 2\n            ''').strip().split('\\n')\n            )\n        self.assertEqual(cue_block.identifier, 'identifier')\n        self.assertEqual(cue_block.start, '00:00:00.500')\n        self.assertEqual(cue_block.end, '00:00:07.000')\n        self.assertListEqual(\n            cue_block.payload,\n            ['Caption #1 line 1', 'Caption #1 line 2']\n            )\n\n\nclass TestWebVTTCommentBlock(unittest.TestCase):\n\n    def test_is_valid(self):\n        self.assertTrue(\n            vtt.WebVTTCommentBlock.is_valid(textwrap.dedent('''\n            NOTE This is a one line comment\n            ''').strip().split('\\n'))\n            )\n\n        self.assertTrue(\n            vtt.WebVTTCommentBlock.is_valid(textwrap.dedent('''\n            NOTE\n            This is a another one line comment\n            ''').strip().split('\\n'))\n            )\n\n        self.assertTrue(\n            vtt.WebVTTCommentBlock.is_valid(textwrap.dedent('''\n            NOTE\n            This is a multi-line comment\n            taking two lines\n            ''').strip().split('\\n'))\n            )\n\n        self.assertFalse(\n            vtt.WebVTTCommentBlock.is_valid(textwrap.dedent('''\n            This is not a comment\n            ''').strip().split('\\n'))\n            )\n\n        self.assertFalse(\n            vtt.WebVTTCommentBlock.is_valid(textwrap.dedent('''\n            # This is not a comment\n            ''').strip().split('\\n'))\n            )\n\n        self.assertFalse(\n            vtt.WebVTTCommentBlock.is_valid(textwrap.dedent('''\n            // This is not a comment\n            ''').strip().split('\\n'))\n            )\n\n    def test_from_lines(self):\n        comment = vtt.WebVTTCommentBlock.from_lines(textwrap.dedent('''\n            NOTE This is a one line comment\n            ''').strip().split('\\n')\n            )\n        self.assertEqual(comment.text, 'This is a one line comment')\n\n        comment = vtt.WebVTTCommentBlock.from_lines(textwrap.dedent('''\n            NOTE\n            This is a multi-line comment\n            taking two lines\n            ''').strip().split('\\n')\n            )\n        self.assertEqual(\n            comment.text,\n            'This is a multi-line comment\\ntaking two lines'\n            )\n\n\nclass TestWebVTTStyleBlock(unittest.TestCase):\n\n    def test_is_valid(self):\n        self.assertTrue(\n            vtt.WebVTTStyleBlock.is_valid(textwrap.dedent('''\n            STYLE\n            ::cue {\n              background-image: linear-gradient(to bottom, dimgray, lightgray);\n              color: papayawhip;\n            }\n            ''').strip().split('\\n'))\n            )\n\n        self.assertTrue(\n            vtt.WebVTTStyleBlock.is_valid(textwrap.dedent('''\n            STYLE\n            ::cue {\n              background-image: linear-gradient(to bottom, dimgray, lightgray);\n              color: papayawhip;\n            }\n            ::cue(b) {\n              color: peachpuff;\n            }\n            ''').strip().split('\\n'))\n            )\n\n        self.assertFalse(\n            vtt.WebVTTStyleBlock.is_valid(textwrap.dedent('''\n            STYLE\n            ::cue {\n              background-image: linear-gradient(to bottom, dimgray, lightgray);\n              color: papayawhip;\n            }\n\n            ::cue(b) {\n              color: peachpuff;\n            }\n            ''').strip().split('\\n'))\n            )\n\n        self.assertFalse(\n            vtt.WebVTTStyleBlock.is_valid(textwrap.dedent('''\n            STYLE\n            ::cue--> {\n              background-image: linear-gradient(to bottom, dimgray, lightgray);\n              color: papayawhip;\n            }\n            ''').strip().split('\\n'))\n            )\n\n        self.assertFalse(\n            vtt.WebVTTStyleBlock.is_valid(textwrap.dedent('''\n            ::cue {\n              background-image: linear-gradient(to bottom, dimgray, lightgray);\n              color: papayawhip;\n            }\n            ''').strip().split('\\n'))\n            )\n\n    def test_from_lines(self):\n        style = vtt.WebVTTStyleBlock.from_lines(textwrap.dedent('''\n            STYLE\n            ::cue {\n              background-image: linear-gradient(to bottom, dimgray, lightgray);\n              color: papayawhip;\n            }\n            ::cue(b) {\n              color: peachpuff;\n            }\n            ''').strip().split('\\n')\n            )\n        self.assertEqual(\n            style.text,\n            textwrap.dedent('''\n            ::cue {\n              background-image: linear-gradient(to bottom, dimgray, lightgray);\n              color: papayawhip;\n            }\n            ::cue(b) {\n              color: peachpuff;\n            }\n            ''').strip()\n            )\n\n\nclass TestVTTModule(unittest.TestCase):\n\n    def test_parse_invalid_format(self):\n        self.assertRaises(\n            MalformedFileError,\n            vtt.parse,\n            textwrap.dedent('''\n                00:00:00.500 --> 00:00:07.000\n                Caption text #1\n\n                00:00:07.000 --> 00:00:11.890\n                Caption text #2\n                ''').strip().split('\\n')\n            )\n\n    def test_parse_captions(self):\n        output = vtt.parse(\n            textwrap.dedent('''\n            WEBVTT\n\n            00:00:00.500 --> 00:00:07.000\n            Caption text #1\n\n            00:00:07.000 --> 00:00:11.890\n            Caption text #2 line 1\n            Caption text #2 line 2\n            ''').strip().split('\\n')\n            )\n        captions = output.captions\n        styles = output.styles\n        self.assertEqual(len(captions), 2)\n        self.assertEqual(len(styles), 0)\n        self.assertIsInstance(captions[0], Caption)\n        self.assertIsInstance(captions[1], Caption)\n        self.assertEqual(\n            str(captions[0]),\n            '00:00:00.500 00:00:07.000 Caption text #1'\n            )\n        self.assertEqual(\n            str(captions[1]),\n            r'00:00:07.000 00:00:11.890 Caption text #2 line 1\\n'\n            'Caption text #2 line 2'\n            )\n\n    def test_parse_styles(self):\n        output = vtt.parse(\n            textwrap.dedent('''\n            WEBVTT\n\n            STYLE\n            ::cue {\n              color: white;\n            }\n\n            STYLE\n            ::cue(.important) {\n              color: red;\n              font-weight: bold;\n            }\n\n            00:00:00.500 --> 00:00:07.000\n            Caption text #1\n            ''').strip().split('\\n')\n            )\n        captions = output.captions\n        styles = output.styles\n        self.assertEqual(len(captions), 1)\n        self.assertEqual(len(styles), 2)\n        self.assertIsInstance(styles[0], Style)\n        self.assertIsInstance(styles[1], Style)\n        self.assertEqual(\n            str(styles[0].text),\n            textwrap.dedent('''\n                ::cue {\n                  color: white;\n                }\n                ''').strip()\n            )\n        self.assertEqual(\n            str(styles[1].text),\n            textwrap.dedent('''\n                ::cue(.important) {\n                  color: red;\n                  font-weight: bold;\n                }\n                ''').strip(),\n            )\n\n    def test_parse_content(self):\n        output = vtt.parse(\n            textwrap.dedent('''\n            WEBVTT\n\n            NOTE This is a testing sample\n\n            NOTE We can see two header comments, a style\n            comment and finally a footer comments\n\n            STYLE\n            ::cue {\n              background-image: linear-gradient(to bottom, dimgray);\n              color: papayawhip;\n            }\n\n            NOTE the following style needs review\n\n            STYLE\n            ::cue {\n              color: white;\n            }\n\n            NOTE Comment for the first caption\n\n            00:00:00.500 --> 00:00:07.000\n            Caption text #1\n\n            NOTE\n            Comment for the second caption\n            that is very long\n\n            00:00:07.000 --> 00:00:11.890\n            Caption text #2 line 1\n            Caption text #2 line 2\n\n            NOTE Copyright 2024\n\n            NOTE end of file\n            ''').strip().split('\\n')\n            )\n        captions = output.captions\n        styles = output.styles\n        self.assertEqual(len(captions), 2)\n        self.assertEqual(len(styles), 2)\n        self.assertIsInstance(captions[0], Caption)\n        self.assertIsInstance(captions[1], Caption)\n        self.assertIsInstance(styles[0], Style)\n        self.assertIsInstance(styles[1], Style)\n        self.assertEqual(\n            str(captions[0]),\n            '00:00:00.500 00:00:07.000 Caption text #1'\n            )\n        self.assertEqual(\n            str(captions[1]),\n            r'00:00:07.000 00:00:11.890 Caption text #2 line 1\\n'\n            'Caption text #2 line 2'\n            )\n        self.assertEqual(\n            str(styles[0].text),\n            textwrap.dedent('''\n                ::cue {\n                  background-image: linear-gradient(to bottom, dimgray);\n                  color: papayawhip;\n                }\n                ''').strip()\n            )\n        self.assertEqual(\n            str(styles[1].text),\n            textwrap.dedent('''\n                ::cue {\n                  color: white;\n                }\n                ''').strip()\n            )\n        self.assertEqual(\n            styles[0].comments,\n            []\n            )\n        self.assertEqual(\n            styles[1].comments,\n            ['the following style needs review']\n            )\n        self.assertEqual(\n            captions[0].comments,\n            ['Comment for the first caption']\n            )\n        self.assertEqual(\n            captions[1].comments,\n            ['Comment for the second caption\\nthat is very long']\n            )\n        self.assertListEqual(output.header_comments,\n                             ['This is a testing sample',\n                              'We can see two header comments, a style\\n'\n                              'comment and finally a footer comments'\n                              ]\n                             )\n        self.assertListEqual(output.footer_comments,\n                             ['Copyright 2024',\n                              'end of file'\n                              ]\n                             )\n\n    def test_write(self):\n        out = io.StringIO()\n        captions = [\n            Caption(start='00:00:00.500',\n                    end='00:00:07.000',\n                    text='Caption #1'\n                    ),\n            Caption(start='00:00:07.000',\n                    end='00:00:11.890',\n                    text=['Caption #2 line 1',\n                          'Caption #2 line 2'\n                          ]\n                    )\n            ]\n        styles = [\n            Style('::cue(b) {\\n  color: peachpuff;\\n}'),\n            Style('::cue {\\n  color: papayawhip;\\n}')\n            ]\n        captions[0].comments.append('Comment for the first caption')\n        captions[1].comments.append('Comment for the second caption')\n        styles[1].comments.append(\n            'Comment for the second style\\nwith two lines'\n            )\n        header_comments = ['header comment', 'begin of the file']\n        footer_comments = ['footer comment', 'end of file']\n\n        vtt.write(\n            out,\n            captions,\n            styles,\n            header_comments,\n            footer_comments\n            )\n\n        out.seek(0)\n\n        self.assertEqual(\n            out.read(),\n            textwrap.dedent('''\n                WEBVTT\n\n                NOTE header comment\n\n                NOTE begin of the file\n\n                STYLE\n                ::cue(b) {\n                  color: peachpuff;\n                }\n\n                NOTE\n                Comment for the second style\n                with two lines\n\n                STYLE\n                ::cue {\n                  color: papayawhip;\n                }\n\n                NOTE Comment for the first caption\n\n                00:00:00.500 --> 00:00:07.000\n                Caption #1\n\n                NOTE Comment for the second caption\n\n                00:00:07.000 --> 00:00:11.890\n                Caption #2 line 1\n                Caption #2 line 2\n\n                NOTE footer comment\n\n                NOTE end of file\n            ''').strip()\n            )\n\n    def test_to_str(self):\n        captions = [\n            Caption(start='00:00:00.500',\n                    end='00:00:07.000',\n                    text='Caption #1'\n                    ),\n            Caption(start='00:00:07.000',\n                    end='00:00:11.890',\n                    text=['Caption #2 line 1',\n                          'Caption #2 line 2'\n                          ]\n                    )\n            ]\n        styles = [\n            Style('::cue(b) {\\n  color: peachpuff;\\n}'),\n            Style('::cue {\\n  color: papayawhip;\\n}')\n            ]\n        captions[0].comments.append('Comment for the first caption')\n        captions[1].comments.append('Comment for the second caption')\n        styles[1].comments.append(\n            'Comment for the second style\\nwith two lines'\n            )\n        header_comments = ['header comment', 'begin of the file']\n        footer_comments = ['footer comment', 'end of file']\n\n        self.assertEqual(\n            vtt.to_str(\n                captions,\n                styles,\n                header_comments,\n                footer_comments\n                ),\n            textwrap.dedent('''\n                WEBVTT\n\n                NOTE header comment\n\n                NOTE begin of the file\n\n                STYLE\n                ::cue(b) {\n                  color: peachpuff;\n                }\n\n                NOTE\n                Comment for the second style\n                with two lines\n\n                STYLE\n                ::cue {\n                  color: papayawhip;\n                }\n\n                NOTE Comment for the first caption\n\n                00:00:00.500 --> 00:00:07.000\n                Caption #1\n\n                NOTE Comment for the second caption\n\n                00:00:07.000 --> 00:00:11.890\n                Caption #2 line 1\n                Caption #2 line 2\n\n                NOTE footer comment\n\n                NOTE end of file\n            ''').strip()\n            )\n"
  },
  {
    "path": "tests/test_webvtt.py",
    "content": "import unittest\nimport os\nimport io\nimport textwrap\nimport warnings\nimport tempfile\nimport pathlib\n\nimport webvtt\nfrom webvtt.models import Caption, Style\nfrom webvtt.utils import CODEC_BOMS\nfrom webvtt.errors import MalformedFileError\n\nPATH_TO_SAMPLES = pathlib.Path(__file__).resolve().parent / 'samples'\n\n\nclass TestWebVTT(unittest.TestCase):\n\n    def test_from_string(self):\n        vtt = webvtt.from_string(textwrap.dedent(\"\"\"\n            WEBVTT\n\n            00:00:00.500 --> 00:00:07.000\n            Caption text #1\n\n            00:00:07.000 --> 00:00:11.890\n            Caption text #2 line 1\n            Caption text #2 line 2\n\n            00:00:11.890 --> 00:00:16.320\n            Caption text #3\n\n            00:00:16.320 --> 00:00:21.580\n            Caption text #4\n            \"\"\").strip()\n            )\n        self.assertEqual(len(vtt), 4)\n        self.assertEqual(\n            str(vtt[0]),\n            '00:00:00.500 00:00:07.000 Caption text #1'\n            )\n        self.assertEqual(\n            str(vtt[1]),\n            r'00:00:07.000 00:00:11.890 Caption text #2 line 1\\n'\n            'Caption text #2 line 2'\n            )\n        self.assertEqual(\n            str(vtt[2]),\n            '00:00:11.890 00:00:16.320 Caption text #3'\n            )\n        self.assertEqual(\n            str(vtt[3]),\n            '00:00:16.320 00:00:21.580 Caption text #4'\n            )\n\n    def test_write_captions(self):\n        out = io.StringIO()\n        vtt = webvtt.read(PATH_TO_SAMPLES / 'one_caption.vtt')\n        new_caption = Caption(start='00:00:07.000',\n                              end='00:00:11.890',\n                              text=['New caption text line1',\n                                    'New caption text line2'\n                                    ]\n                              )\n        vtt.captions.append(new_caption)\n        vtt.write(out)\n\n        out.seek(0)\n\n        self.assertEqual(\n            out.read(),\n            textwrap.dedent('''\n                WEBVTT\n\n                00:00:00.500 --> 00:00:07.000\n                Caption text #1\n\n                00:00:07.000 --> 00:00:11.890\n                New caption text line1\n                New caption text line2\n            ''').strip() + '\\n'\n            )\n\n    def test_write_captions_in_srt(self):\n        out = io.StringIO()\n        vtt = webvtt.read(PATH_TO_SAMPLES / 'one_caption.vtt')\n        new_caption = Caption(start='00:00:07.000',\n                              end='00:00:11.890',\n                              text=['New caption text line1',\n                                    'New caption text line2'\n                                    ]\n                              )\n        vtt.captions.append(new_caption)\n        vtt.write(out, format='srt')\n\n        out.seek(0)\n        self.assertEqual(\n            out.read(),\n            textwrap.dedent('''\n                1\n                00:00:00,500 --> 00:00:07,000\n                Caption text #1\n\n                2\n                00:00:07,000 --> 00:00:11,890\n                New caption text line1\n                New caption text line2\n            ''').strip()\n            )\n\n    def test_write_captions_in_srt_no_cuetags(self):\n        \"\"\"https://github.com/glut23/webvtt-py/issues/56\"\"\"\n        out = io.StringIO()\n        vtt = webvtt.read(PATH_TO_SAMPLES / 'cue_tags.vtt')\n        vtt.write(out, format='srt')\n\n        out.seek(0)\n        self.assertEqual(\n            out.read(),\n            textwrap.dedent('''\n            1\n            00:00:16,500 --> 00:00:18,500\n            When the moon hits your eye\n\n            2\n            00:00:18,500 --> 00:00:20,500\n            Like a big-a pizza pie\n\n            3\n            00:00:20,500 --> 00:00:21,500\n            That's amore\n            ''').strip()\n            )\n\n    def test_write_captions_in_unsupported_format(self):\n        self.assertRaises(\n            ValueError,\n            webvtt.WebVTT().write,\n            io.StringIO(),\n            format='ttt'\n            )\n\n    def test_save_captions(self):\n        with tempfile.NamedTemporaryFile('w', suffix='.vtt') as f:\n            f.write((PATH_TO_SAMPLES / 'one_caption.vtt').read_text())\n            f.flush()\n\n            vtt = webvtt.read(f.name)\n            new_caption = Caption(start='00:00:07.000',\n                                  end='00:00:11.890',\n                                  text=['New caption text line1',\n                                        'New caption text line2'\n                                        ]\n                                  )\n            vtt.captions.append(new_caption)\n            vtt.save()\n            f.flush()\n\n            self.assertEqual(\n                pathlib.Path(f.name).read_text(),\n                textwrap.dedent('''\n                    WEBVTT\n\n                    00:00:00.500 --> 00:00:07.000\n                    Caption text #1\n\n                    00:00:07.000 --> 00:00:11.890\n                    New caption text line1\n                    New caption text line2\n                    ''').strip() + '\\n'\n                )\n\n    def test_srt_conversion(self):\n        with tempfile.TemporaryDirectory() as td:\n            with open(pathlib.Path(td) / 'one_caption.srt', 'w') as f:\n                f.write((PATH_TO_SAMPLES / 'one_caption.srt').read_text())\n\n            webvtt.from_srt(\n                pathlib.Path(td) / 'one_caption.srt'\n                ).save()\n\n            self.assertTrue(\n                os.path.exists(pathlib.Path(td) / 'one_caption.vtt')\n                )\n            self.assertEqual(\n                (pathlib.Path(td) / 'one_caption.vtt').read_text(),\n                textwrap.dedent('''\n                    WEBVTT\n\n                    00:00:00.500 --> 00:00:07.000\n                    Caption text #1\n                    ''').strip() + '\\n'\n                )\n\n    def test_sbv_conversion(self):\n        with tempfile.TemporaryDirectory() as td:\n            with open(pathlib.Path(td) / 'two_captions.sbv', 'w') as f:\n                f.write(\n                    (PATH_TO_SAMPLES / 'two_captions.sbv').read_text()\n                    )\n\n            webvtt.from_sbv(\n                pathlib.Path(td) / 'two_captions.sbv'\n                ).save()\n\n            self.assertTrue(\n                os.path.exists(pathlib.Path(td) / 'two_captions.vtt')\n                )\n            self.assertEqual(\n                (pathlib.Path(td) / 'two_captions.vtt').read_text(),\n                textwrap.dedent('''\n                    WEBVTT\n\n                    00:00:00.378 --> 00:00:11.378\n                    Caption text #1\n\n                    00:00:11.378 --> 00:00:12.305\n                    Caption text #2 (line 1)\n                    Caption text #2 (line 2)\n                    ''').strip() + '\\n'\n                )\n\n    def test_save_to_other_location(self):\n        with tempfile.TemporaryDirectory() as td:\n            webvtt.read(\n                PATH_TO_SAMPLES / 'one_caption.vtt'\n                ).save(td)\n\n            self.assertTrue(\n                os.path.exists(pathlib.Path(td) / 'one_caption.vtt')\n                )\n\n    def test_save_specific_filename(self):\n        with tempfile.TemporaryDirectory() as td:\n            webvtt.read(\n                PATH_TO_SAMPLES / 'one_caption.vtt'\n                ).save(\n                    pathlib.Path(td) / 'one_caption_new.vtt'\n                )\n\n            self.assertTrue(\n                os.path.exists(pathlib.Path(td) / 'one_caption_new.vtt')\n                )\n\n    def test_save_specific_filename_no_extension(self):\n        with tempfile.TemporaryDirectory() as td:\n            webvtt.read(\n                PATH_TO_SAMPLES / 'one_caption.vtt'\n                ).save(\n                    pathlib.Path(td) / 'one_caption_new'\n                )\n\n            self.assertTrue(\n                os.path.exists(pathlib.Path(td) / 'one_caption_new.vtt')\n                )\n\n    def test_from_buffer(self):\n        with open(PATH_TO_SAMPLES / 'sample.vtt', 'r', encoding='utf-8') as f:\n            vtt = webvtt.from_buffer(f)\n            self.assertEqual(len(vtt), 16)\n            self.assertEqual(\n                str(vtt),\n                textwrap.dedent('''\n                    00:00:00.500 00:00:07.000 Caption text #1\n                    00:00:07.000 00:00:11.890 Caption text #2\n                    00:00:11.890 00:00:16.320 Caption text #3\n                    00:00:16.320 00:00:21.580 Caption text #4\n                    00:00:21.580 00:00:23.880 Caption text #5\n                    00:00:23.880 00:00:27.280 Caption text #6\n                    00:00:27.280 00:00:30.280 Caption text #7\n                    00:00:30.280 00:00:36.510 Caption text #8\n                    00:00:36.510 00:00:38.870 Caption text #9\n                    00:00:38.870 00:00:45.000 Caption text #10\n                    00:00:45.000 00:00:47.000 Caption text #11\n                    00:00:47.000 00:00:50.970 Caption text #12\n                    00:00:50.970 00:00:54.440 Caption text #13\n                    00:00:54.440 00:00:58.600 Caption text #14\n                    00:00:58.600 00:01:01.350 Caption text #15\n                    00:01:01.350 00:01:04.300 Caption text #16\n                    '''\n                    ).strip())\n\n    def test_deprecated_read_buffer(self):\n        with open(PATH_TO_SAMPLES / 'sample.vtt', 'r', encoding='utf-8') as f:\n            with warnings.catch_warnings(record=True) as warns:\n                warnings.simplefilter('always')\n                vtt = webvtt.read_buffer(f)\n\n                self.assertIsInstance(vtt.captions, list)\n                self.assertEqual(\n                    'Deprecated: use from_buffer instead.',\n                    str(warns[-1].message)\n                    )\n\n    def test_read_memory_buffer(self):\n        buffer = io.StringIO(\n            (PATH_TO_SAMPLES / 'sample.vtt').read_text()\n            )\n\n        self.assertIsInstance(\n            webvtt.from_buffer(buffer).captions,\n            list\n            )\n\n    def test_read_memory_buffer_carriage_return(self):\n        \"\"\"https://github.com/glut23/webvtt-py/issues/29\"\"\"\n        buffer = io.StringIO(textwrap.dedent('''\\\n            WEBVTT\\r\n            \\r\n            00:00:00.500 --> 00:00:07.000\\r\n            Caption text #1\\r\n            \\r\n            00:00:07.000 --> 00:00:11.890\\r\n            Caption text #2\\r\n            \\r\n            00:00:11.890 --> 00:00:16.320\\r\n            Caption text #3\\r\n        ''')\n        )\n\n        self.assertEqual(\n            len(webvtt.from_buffer(buffer).captions),\n            3\n            )\n\n    def test_read_malformed_buffer(self):\n        malformed_payloads = ['', 'MOCK MALFORMED CONTENT']\n        for payload in malformed_payloads:\n            buffer = io.StringIO(payload)\n            with self.assertRaises(MalformedFileError):\n                webvtt.from_buffer(buffer)\n\n    def test_read_buffer_for_vtt_content(self):\n        buffer = io.StringIO(textwrap.dedent('''\\\n            WEBVTT\\r\n            \\r\n            00:00:00.500 --> 00:00:07.000\\r\n            Caption text #1\\r\n            \\r\n            00:00:07.000 --> 00:00:11.890\\r\n            Caption text #2\\r\n            \\r\n            00:00:11.890 --> 00:00:16.320\\r\n            Caption text #3\\r\n            ''')\n            )\n        vtt = webvtt.from_buffer(buffer, format='vtt')\n        self.assertEqual(len(vtt), 3)\n\n        self.assertEqual(\n            str(vtt[0]),\n            '00:00:00.500 00:00:07.000 Caption text #1'\n            )\n        self.assertEqual(\n            str(vtt[1]),\n            '00:00:07.000 00:00:11.890 Caption text #2'\n            )\n        self.assertEqual(\n            str(vtt[2]),\n            '00:00:11.890 00:00:16.320 Caption text #3'\n            )\n\n    def test_read_buffer_for_srt_content(self):\n        buffer = io.StringIO(textwrap.dedent('''\\\n            0\\r\n            00:00:00,500 --> 00:00:07,000\\r\n            Caption text #1\\r\n            \\r\n            1\\r\n            00:00:07,000 --> 00:00:11,890\\r\n            Caption text #2\\r\n            \\r\n            2\\r\n            00:00:11,890 --> 00:00:16,320\\r\n            Caption text #3\\r\n            ''')\n            )\n        vtt = webvtt.from_buffer(buffer, format='srt')\n        self.assertEqual(len(vtt), 3)\n\n        self.assertEqual(\n            str(vtt[0]),\n            '00:00:00.500 00:00:07.000 Caption text #1'\n            )\n        self.assertEqual(\n            str(vtt[1]),\n            '00:00:07.000 00:00:11.890 Caption text #2'\n            )\n        self.assertEqual(\n            str(vtt[2]),\n            '00:00:11.890 00:00:16.320 Caption text #3'\n            )\n\n    def test_read_buffer_for_sbv_content(self):\n        buffer = io.StringIO(textwrap.dedent('''\\\n            00:00:00.500,00:00:07.000\\r\n            Caption text #1\\r\n            \\r\n            00:00:07.000,00:00:11.890\\r\n            Caption text #2\\r\n            \\r\n            00:00:11.890,00:00:16.320\\r\n            Caption text #3\\r\n            ''')\n            )\n        vtt = webvtt.from_buffer(buffer, format='sbv')\n        self.assertEqual(len(vtt), 3)\n\n        self.assertEqual(\n            str(vtt[0]),\n            '00:00:00.500 00:00:07.000 Caption text #1'\n            )\n        self.assertEqual(\n            str(vtt[1]),\n            '00:00:07.000 00:00:11.890 Caption text #2'\n            )\n        self.assertEqual(\n            str(vtt[2]),\n            '00:00:11.890 00:00:16.320 Caption text #3'\n            )\n\n    def test_read_buffer_unsupported_format(self):\n        self.assertRaises(\n            ValueError,\n            webvtt.from_buffer,\n            io.StringIO(),\n            format='ttt'\n            )\n\n    def test_read_bytesio_buffer_for_srt_content(self):\n        buffer = io.BytesIO(textwrap.dedent('''\\\n            0\\r\n            00:00:00,500 --> 00:00:07,000\\r\n            Caption text #1\\r\n            \\r\n            1\\r\n            00:00:07,000 --> 00:00:11,890\\r\n            Caption text #2\\r\n            \\r\n            2\\r\n            00:00:11,890 --> 00:00:16,320\\r\n            Caption text #3\\r\n            ''').encode('utf-8')\n            )\n        vtt = webvtt.from_buffer(buffer, format='srt')\n        self.assertEqual(len(vtt), 3)\n\n        self.assertEqual(\n            str(vtt[0]),\n            '00:00:00.500 00:00:07.000 Caption text #1'\n            )\n        self.assertEqual(\n            str(vtt[1]),\n            '00:00:07.000 00:00:11.890 Caption text #2'\n            )\n        self.assertEqual(\n            str(vtt[2]),\n            '00:00:11.890 00:00:16.320 Caption text #3'\n            )\n\n    def test_captions(self):\n        captions = webvtt.read(PATH_TO_SAMPLES / 'sample.vtt').captions\n        self.assertIsInstance(\n            captions,\n            list\n            )\n        self.assertEqual(len(captions), 16)\n\n    def test_sequence_iteration(self):\n        vtt = webvtt.read(PATH_TO_SAMPLES / 'sample.vtt')\n        self.assertIsInstance(vtt[0], Caption)\n        self.assertEqual(len(vtt), len(vtt.captions))\n\n    def test_save_no_filename(self):\n        self.assertRaises(\n            webvtt.errors.MissingFilenameError,\n            webvtt.WebVTT().save\n            )\n\n    def test_save_with_path_to_dir_no_filename(self):\n        with tempfile.TemporaryDirectory() as td:\n            self.assertRaises(\n                webvtt.errors.MissingFilenameError,\n                webvtt.WebVTT().save,\n                td\n                )\n\n    def test_set_styles_from_text(self):\n        style = Style('::cue(b) {\\n  color: peachpuff;\\n}')\n        self.assertListEqual(\n            style.lines,\n            ['::cue(b) {', '  color: peachpuff;', '}']\n            )\n\n    def test_save_identifiers(self):\n        with tempfile.NamedTemporaryFile('w', suffix='.vtt') as f:\n            webvtt.read(\n                PATH_TO_SAMPLES / 'using_identifiers.vtt'\n                ).save(\n                    f.name\n                    )\n\n            self.assertListEqual(\n                pathlib.Path(f.name).read_text().splitlines(),\n                [\n                    'WEBVTT',\n                    '',\n                    '00:00:00.500 --> 00:00:07.000',\n                    'Caption text #1',\n                    '',\n                    'second caption',\n                    '00:00:07.000 --> 00:00:11.890',\n                    'Caption text #2',\n                    '',\n                    '00:00:11.890 --> 00:00:16.320',\n                    'Caption text #3',\n                    '',\n                    '4',\n                    '00:00:16.320 --> 00:00:21.580',\n                    'Caption text #4',\n                    '',\n                    '00:00:21.580 --> 00:00:23.880',\n                    'Caption text #5',\n                    '',\n                    '00:00:23.880 --> 00:00:27.280',\n                    'Caption text #6'\n                    ]\n                )\n\n    def test_save_updated_identifiers(self):\n        vtt = webvtt.read(PATH_TO_SAMPLES / 'using_identifiers.vtt')\n        vtt.captions[0].identifier = 'first caption'\n        vtt.captions[1].identifier = None\n        vtt.captions[3].identifier = '44'\n        last_caption = Caption(start='00:00:27.280',\n                               end='00:00:29.200',\n                               text='Caption text #7'\n                               )\n        last_caption.identifier = 'last caption'\n        vtt.captions.append(last_caption)\n\n        with tempfile.NamedTemporaryFile('w', suffix='.vtt') as f:\n            vtt.save(f.name)\n\n            self.assertListEqual(\n                pathlib.Path(f.name).read_text().splitlines(),\n                [\n                    'WEBVTT',\n                    '',\n                    'first caption',\n                    '00:00:00.500 --> 00:00:07.000',\n                    'Caption text #1',\n                    '',\n                    '00:00:07.000 --> 00:00:11.890',\n                    'Caption text #2',\n                    '',\n                    '00:00:11.890 --> 00:00:16.320',\n                    'Caption text #3',\n                    '',\n                    '44',\n                    '00:00:16.320 --> 00:00:21.580',\n                    'Caption text #4',\n                    '',\n                    '00:00:21.580 --> 00:00:23.880',\n                    'Caption text #5',\n                    '',\n                    '00:00:23.880 --> 00:00:27.280',\n                    'Caption text #6',\n                    '',\n                    'last caption',\n                    '00:00:27.280 --> 00:00:29.200',\n                    'Caption text #7'\n                    ]\n                )\n\n    def test_content_formatting(self):\n        \"\"\"\n        Verify that content property returns the correctly formatted webvtt.\n        \"\"\"\n        captions = [\n            Caption(start='00:00:00.500',\n                    end='00:00:07.000',\n                    text=['Caption test line 1', 'Caption test line 2']\n                    ),\n            Caption(start='00:00:08.000',\n                    end='00:00:15.000',\n                    text=['Caption test line 3', 'Caption test line 4']\n                    ),\n            ]\n\n        self.assertEqual(\n            webvtt.WebVTT(captions=captions).content,\n            textwrap.dedent(\"\"\"\n                    WEBVTT\n\n                    00:00:00.500 --> 00:00:07.000\n                    Caption test line 1\n                    Caption test line 2\n\n                    00:00:08.000 --> 00:00:15.000\n                    Caption test line 3\n                    Caption test line 4\n                    \"\"\").strip() + '\\n'\n            )\n\n    def test_repr(self):\n        test_file = PATH_TO_SAMPLES / 'sample.vtt'\n        self.assertEqual(\n            repr(webvtt.read(test_file)),\n            f\"<WebVTT file='{test_file}' encoding='utf-8'>\"\n            )\n\n    def test_str(self):\n        self.assertEqual(\n            str(webvtt.read(PATH_TO_SAMPLES / 'sample.vtt')),\n            textwrap.dedent(\"\"\"\n                00:00:00.500 00:00:07.000 Caption text #1\n                00:00:07.000 00:00:11.890 Caption text #2\n                00:00:11.890 00:00:16.320 Caption text #3\n                00:00:16.320 00:00:21.580 Caption text #4\n                00:00:21.580 00:00:23.880 Caption text #5\n                00:00:23.880 00:00:27.280 Caption text #6\n                00:00:27.280 00:00:30.280 Caption text #7\n                00:00:30.280 00:00:36.510 Caption text #8\n                00:00:36.510 00:00:38.870 Caption text #9\n                00:00:38.870 00:00:45.000 Caption text #10\n                00:00:45.000 00:00:47.000 Caption text #11\n                00:00:47.000 00:00:50.970 Caption text #12\n                00:00:50.970 00:00:54.440 Caption text #13\n                00:00:54.440 00:00:58.600 Caption text #14\n                00:00:58.600 00:01:01.350 Caption text #15\n                00:01:01.350 00:01:04.300 Caption text #16\n            \"\"\").strip()\n            )\n\n    def test_parse_invalid_file(self):\n        self.assertRaises(\n            MalformedFileError,\n            webvtt.read,\n            PATH_TO_SAMPLES / 'invalid.vtt'\n            )\n\n    def test_file_not_found(self):\n        self.assertRaises(\n            FileNotFoundError,\n            webvtt.read,\n            'nowhere'\n            )\n\n    def test_total_length(self):\n        self.assertEqual(\n            webvtt.read(PATH_TO_SAMPLES / 'sample.vtt').total_length,\n            64\n            )\n\n    def test_total_length_no_captions(self):\n        self.assertEqual(\n            webvtt.WebVTT().total_length,\n            0\n            )\n\n    def test_parse_empty_file(self):\n        self.assertRaises(\n            MalformedFileError,\n            webvtt.read,\n            PATH_TO_SAMPLES / 'empty.vtt'\n            )\n\n    def test_parse_invalid_timeframe_line(self):\n        good_captions = len(\n            webvtt.read(PATH_TO_SAMPLES / 'invalid_timeframe.vtt').captions\n            )\n        self.assertEqual(good_captions, 6)\n\n    def test_parse_invalid_timeframe_in_cue_text(self):\n        vtt = webvtt.read(\n            PATH_TO_SAMPLES / 'invalid_timeframe_in_cue_text.vtt'\n            )\n        self.assertEqual(2, len(vtt.captions))\n        self.assertEqual('Caption text #3', vtt.captions[1].text)\n\n    def test_parse_get_caption_data(self):\n        vtt = webvtt.read(PATH_TO_SAMPLES / 'one_caption.vtt')\n        self.assertEqual(vtt.captions[0].start_in_seconds, 0)\n        self.assertEqual(vtt.captions[0].start, '00:00:00.500')\n        self.assertEqual(vtt.captions[0].end_in_seconds, 7)\n        self.assertEqual(vtt.captions[0].end, '00:00:07.000')\n        self.assertEqual(vtt.captions[0].lines[0], 'Caption text #1')\n        self.assertEqual(len(vtt.captions[0].lines), 1)\n\n    def test_caption_without_timeframe(self):\n        vtt = webvtt.read(PATH_TO_SAMPLES / 'missing_timeframe.vtt')\n        self.assertEqual(len(vtt.captions), 6)\n\n    def test_caption_without_cue_text(self):\n        vtt = webvtt.read(PATH_TO_SAMPLES / 'missing_caption_text.vtt')\n        self.assertEqual(len(vtt.captions), 4)\n\n    def test_timestamps_format(self):\n        vtt = webvtt.read(PATH_TO_SAMPLES / 'sample.vtt')\n        self.assertEqual(vtt.captions[2].start, '00:00:11.890')\n        self.assertEqual(vtt.captions[2].end, '00:00:16.320')\n\n    def test_parse_timestamp(self):\n        self.assertEqual(\n            Caption(start='02:03:11.890').start_in_seconds,\n            7391\n            )\n\n    def test_captions_attribute(self):\n        self.assertListEqual(webvtt.WebVTT().captions, [])\n\n    def test_metadata_headers(self):\n        vtt = webvtt.read(PATH_TO_SAMPLES / 'metadata_headers.vtt')\n        self.assertEqual(len(vtt.captions), 2)\n\n    def test_metadata_headers_multiline(self):\n        vtt = webvtt.read(PATH_TO_SAMPLES / 'metadata_headers_multiline.vtt')\n        self.assertEqual(len(vtt.captions), 2)\n\n    def test_parse_identifiers(self):\n        vtt = webvtt.read(PATH_TO_SAMPLES / 'using_identifiers.vtt')\n        self.assertEqual(len(vtt.captions), 6)\n\n        self.assertEqual(vtt.captions[1].identifier, 'second caption')\n        self.assertEqual(vtt.captions[2].identifier, None)\n        self.assertEqual(vtt.captions[3].identifier, '4')\n\n    def test_parse_comments(self):\n        vtt = webvtt.read(PATH_TO_SAMPLES / 'comments.vtt')\n        self.assertEqual(len(vtt.captions), 3)\n        self.assertListEqual(\n            vtt.captions[0].lines,\n            ['- Ta en kopp varmt te.',\n             '- Det är inte varmt.']\n            )\n        self.assertListEqual(\n            vtt.captions[0].comments,\n            []\n            )\n        self.assertListEqual(\n            vtt.captions[1].comments,\n            []\n            )\n        self.assertEqual(\n            vtt.captions[2].text,\n            '- Ta en kopp'\n            )\n        self.assertListEqual(\n            vtt.captions[2].comments,\n            ['This last line may not translate well.']\n            )\n        self.assertListEqual(\n            vtt.header_comments,\n            ['This translation was done by Kyle so that\\n'\n             'some friends can watch it with their parents.'\n             ]\n            )\n        self.assertListEqual(\n            vtt.footer_comments,\n            ['end of file']\n            )\n\n    def test_parse_styles(self):\n        vtt = webvtt.read(PATH_TO_SAMPLES / 'styles.vtt')\n        self.assertEqual(len(vtt.captions), 1)\n        self.assertEqual(\n            vtt.styles[0].text,\n            '::cue {\\n  background-image: linear-gradient(to bottom, '\n            'dimgray, lightgray);\\n  color: papayawhip;\\n}'\n            )\n\n    def test_parse_styles_with_comments(self):\n        vtt = webvtt.read(PATH_TO_SAMPLES / 'styles_with_comments.vtt')\n        self.assertEqual(len(vtt.captions), 1)\n        self.assertEqual(len(vtt.styles), 2)\n        self.assertEqual(\n            vtt.styles[0].comments,\n            []\n            )\n        self.assertEqual(\n            vtt.styles[0].text,\n            '::cue {\\n'\n            '  background-image: linear-gradient(to bottom, dimgray, '\n            'lightgray);\\n'\n            '  color: papayawhip;\\n'\n            '}'\n            )\n        self.assertEqual(\n            vtt.styles[1].comments,\n            ['This is the second block of styles',\n             'Multiline comment for the same\\nsecond block of styles'\n             ]\n            )\n        self.assertEqual(\n            vtt.styles[1].text,\n            '::cue(b) {\\n'\n            '  color: peachpuff;\\n'\n            '}'\n            )\n        self.assertListEqual(\n            vtt.header_comments,\n            ['Sample of comments with styles']\n            )\n        self.assertListEqual(\n            vtt.footer_comments,\n            []\n            )\n\n    def test_multiple_comments_everywhere(self):\n        vtt = webvtt.WebVTT.from_string(textwrap.dedent(\"\"\"\n            WEBVTT\n\n            NOTE Test file\n\n            NOTE this file is testing multiple comments\n            in different places\n\n            STYLE\n            ::cue {\n              background-image: linear-gradient(to bottom, dimgray, lightgray);\n              color: papayawhip;\n            }\n\n            NOTE this style uses nice color\n\n            NOTE check how it looks before proceeding\n\n            STYLE\n            ::cue(b) {\n              color: peachpuff;\n            }\n\n            00:00:00.500 --> 00:00:07.000\n            Caption text #1\n\n            NOTE next caption has two lines\n\n            NOTE needs review\n\n            00:00:07.000 --> 00:00:11.890\n            Caption text #2 line 1\n            Caption text #2 line 2\n\n            00:00:11.890 --> 00:00:16.320\n            Caption text #3\n\n            00:00:16.320 --> 00:00:21.580\n            Caption text #4\n\n            NOTE Copyright 2024\n\n            NOTE this is the end of the file\n            \"\"\").strip()\n            )\n\n        self.assertListEqual(\n            vtt.header_comments,\n            ['Test file',\n             'this file is testing multiple comments\\nin different places'\n             ]\n            )\n        self.assertListEqual(\n            vtt.footer_comments,\n            ['Copyright 2024',\n             'this is the end of the file'\n             ]\n            )\n        self.assertListEqual(\n            vtt.captions[0].comments,\n            []\n            )\n        self.assertListEqual(\n            vtt.captions[1].comments,\n            ['next caption has two lines',\n             'needs review'\n             ]\n            )\n        self.assertListEqual(\n            vtt.captions[2].comments,\n            []\n            )\n        self.assertListEqual(\n            vtt.captions[3].comments,\n            []\n            )\n        self.assertListEqual(\n            vtt.styles[0].comments,\n            []\n            )\n        self.assertListEqual(\n            vtt.styles[1].comments,\n            ['this style uses nice color',\n             'check how it looks before proceeding'\n             ]\n            )\n\n    def test_comments_in_new_file(self):\n        with tempfile.NamedTemporaryFile('r', suffix='.vtt') as f:\n            vtt = webvtt.WebVTT()\n            vtt.header_comments.append('This is a header comment')\n            vtt.header_comments.append(\n                'where we can see a\\ntwo line comment'\n                )\n            vtt.styles.append(\n                Style('::cue(b) {\\n  color: peachpuff;\\n}')\n                )\n            style = Style('::cue {\\n  color: papayawhip;\\n}')\n            style.comments.append('Another style to test\\nthe look and feel')\n            style.comments.append('Please check')\n            vtt.styles.append(style)\n            vtt.captions.append(\n                Caption(start='00:00:00.500',\n                        end='00:00:07.000',\n                        text='Caption #1',\n                        )\n                )\n            caption = Caption(start='00:00:07.000',\n                              end='00:00:11.890',\n                              text='Caption #2'\n                              )\n            caption.comments.append(\n                'Second caption may be a bit off\\nand needs checking'\n                )\n            caption.comments.append('Confirm if it displays correctly')\n            vtt.captions.append(caption)\n            vtt.footer_comments.append('This is a footer comment')\n            vtt.footer_comments.append(\n                'where we can also see a\\ntwo line comment'\n                )\n\n            vtt.save(f.name)\n            self.assertEqual(\n                f.read(),\n                textwrap.dedent('''\n                    WEBVTT\n\n                    NOTE This is a header comment\n\n                    NOTE\n                    where we can see a\n                    two line comment\n\n                    STYLE\n                    ::cue(b) {\n                      color: peachpuff;\n                    }\n\n                    NOTE\n                    Another style to test\n                    the look and feel\n\n                    NOTE Please check\n\n                    STYLE\n                    ::cue {\n                      color: papayawhip;\n                    }\n\n                    00:00:00.500 --> 00:00:07.000\n                    Caption #1\n\n                    NOTE\n                    Second caption may be a bit off\n                    and needs checking\n\n                    NOTE Confirm if it displays correctly\n\n                    00:00:07.000 --> 00:00:11.890\n                    Caption #2\n\n                    NOTE This is a footer comment\n\n                    NOTE\n                    where we can also see a\n                    two line comment\n                    ''').strip()\n                )\n\n    def test_clean_cue_tags(self):\n        vtt = webvtt.read(PATH_TO_SAMPLES / 'cue_tags.vtt')\n        self.assertEqual(\n            vtt.captions[1].text,\n            'Like a big-a pizza pie'\n            )\n        self.assertEqual(\n            vtt.captions[2].text,\n            'That\\'s amore'\n            )\n\n    def test_parse_captions_with_bom(self):\n        vtt = webvtt.read(PATH_TO_SAMPLES / 'captions_with_bom.vtt')\n        self.assertEqual(len(vtt.captions), 4)\n\n    def test_empty_lines_are_not_included_in_result(self):\n        vtt = webvtt.read(PATH_TO_SAMPLES / 'netflix_chicas_del_cable.vtt')\n        self.assertEqual(vtt.captions[0].text, \"[Alba] En 1928,\")\n        self.assertEqual(\n            vtt.captions[-2].text,\n            \"Diez años no son suficientes\\npara olvidarte...\"\n            )\n\n    def test_can_parse_youtube_dl_files(self):\n        vtt = webvtt.read(PATH_TO_SAMPLES / 'youtube_dl.vtt')\n        self.assertEqual(\n            \"this will happen is I'm telling\\n \",\n            vtt.captions[2].text\n            )\n\n    def test_parse_voice_spans(self):\n        vtt = webvtt.from_string(textwrap.dedent(\"\"\"\n            WEBVTT\n\n            00:00:00.000 --> 00:00:00.800\n            <v.quiet.slow Lisa Simpson>Knock knock</v>\n\n            00:00:02.100 --> 00:00:06.500\n            <v Homer Simpson>Who's there?</v>\n\n            00:00:10.530 --> 00:00:11.090\n            <v.loud Lisa Simpson>Atish</v>\n            \"\"\").strip()\n            )\n        self.assertEqual(len(vtt), 3)\n        self.assertEqual(\n            str(vtt[0]),\n            '00:00:00.000 00:00:00.800 Knock knock'\n            )\n        self.assertEqual(\n            vtt[0].voice,\n            'Lisa Simpson'\n            )\n        self.assertEqual(\n            str(vtt[1]),\n            '00:00:02.100 00:00:06.500 Who\\'s there?'\n            )\n        self.assertEqual(\n            vtt[1].voice,\n            'Homer Simpson'\n            )\n        self.assertEqual(\n            str(vtt[2]),\n            '00:00:10.530 00:00:11.090 Atish'\n            )\n        self.assertEqual(\n            vtt[2].voice,\n            'Lisa Simpson'\n            )\n\n    def test_parse_caption_not_a_voice_span(self):\n        vtt = webvtt.from_string(textwrap.dedent(\"\"\"\n            WEBVTT\n\n            00:00:00.000 --> 00:00:00.800\n            <v Not an actual voice span here\n            \"\"\").strip()\n            )\n        self.assertEqual(len(vtt), 1)\n        self.assertEqual(\n            str(vtt[0]),\n            '00:00:00.000 00:00:00.800 <v Not an actual voice span here'\n            )\n        self.assertIsNone(vtt[0].voice)\n\n\nclass TestParseSRT(unittest.TestCase):\n\n    def test_parse_empty_file(self):\n        self.assertRaises(\n            webvtt.errors.MalformedFileError,\n            webvtt.from_srt,\n            # We reuse this file as it is empty and serves the purpose.\n            PATH_TO_SAMPLES / 'empty.vtt'\n            )\n\n    def test_invalid_format(self):\n        for i in range(1, 5):\n            self.assertRaises(\n                MalformedFileError,\n                webvtt.from_srt,\n                PATH_TO_SAMPLES / f'invalid_format{i}.srt'\n                )\n\n    def test_total_length(self):\n        self.assertEqual(\n            webvtt.from_srt(PATH_TO_SAMPLES / 'sample.srt').total_length,\n            23\n            )\n\n    def test_parse_captions(self):\n        self.assertTrue(\n            webvtt.from_srt(PATH_TO_SAMPLES / 'sample.srt').captions\n            )\n\n    def test_missing_timeframe_line(self):\n        self.assertEqual(\n            len(webvtt.from_srt(\n                PATH_TO_SAMPLES / 'missing_timeframe.srt').captions\n                ),\n            4\n            )\n\n    def test_empty_caption_text(self):\n        self.assertTrue(\n            webvtt.from_srt(\n                PATH_TO_SAMPLES / 'missing_caption_text.srt').captions\n            )\n\n    def test_empty_gets_removed(self):\n        captions = webvtt.from_srt(\n            PATH_TO_SAMPLES / 'missing_caption_text.srt'\n            ).captions\n        self.assertEqual(len(captions), 4)\n\n    def test_invalid_timestamp(self):\n        self.assertEqual(\n            len(webvtt.from_srt(\n                PATH_TO_SAMPLES / 'invalid_timeframe.srt'\n                ).captions),\n            4\n            )\n\n    def test_timestamps_format(self):\n        vtt = webvtt.from_srt(PATH_TO_SAMPLES / 'sample.srt')\n        self.assertEqual(vtt.captions[2].start, '00:00:11.890')\n        self.assertEqual(vtt.captions[2].end, '00:00:16.320')\n\n    def test_parse_get_caption_data(self):\n        vtt = webvtt.from_srt(PATH_TO_SAMPLES / 'one_caption.srt')\n        self.assertEqual(vtt.captions[0].start_in_seconds, 0)\n        self.assertEqual(vtt.captions[0].start, '00:00:00.500')\n        self.assertEqual(vtt.captions[0].end_in_seconds, 7)\n        self.assertEqual(vtt.captions[0].end, '00:00:07.000')\n        self.assertEqual(vtt.captions[0].lines[0], 'Caption text #1')\n        self.assertEqual(len(vtt.captions[0].lines), 1)\n\n\nclass TestParseSBV(unittest.TestCase):\n\n    def test_parse_empty_file(self):\n        self.assertRaises(\n            MalformedFileError,\n            webvtt.from_sbv,\n            # We reuse this file as it is empty and serves the purpose.\n            PATH_TO_SAMPLES / 'empty.vtt'\n            )\n\n    def test_invalid_format(self):\n        self.assertRaises(\n            MalformedFileError,\n            webvtt.from_sbv,\n            PATH_TO_SAMPLES / 'invalid_format.sbv'\n            )\n\n    def test_total_length(self):\n        self.assertEqual(\n            webvtt.from_sbv(PATH_TO_SAMPLES / 'sample.sbv').total_length,\n            16\n            )\n\n    def test_parse_captions(self):\n        self.assertEqual(\n            len(webvtt.from_sbv(PATH_TO_SAMPLES / 'sample.sbv').captions),\n            5\n            )\n\n    def test_missing_timeframe_line(self):\n        self.assertEqual(\n            len(webvtt.from_sbv(\n                PATH_TO_SAMPLES / 'missing_timeframe.sbv'\n                ).captions),\n            4\n            )\n\n    def test_missing_caption_text(self):\n        self.assertTrue(\n            webvtt.from_sbv(\n                PATH_TO_SAMPLES / 'missing_caption_text.sbv'\n                ).captions\n            )\n\n    def test_invalid_timestamp(self):\n        self.assertEqual(\n            len(webvtt.from_sbv(\n                PATH_TO_SAMPLES / 'invalid_timeframe.sbv'\n                ).captions),\n            4\n            )\n\n    def test_timestamps_format(self):\n        vtt = webvtt.from_sbv(PATH_TO_SAMPLES / 'sample.sbv')\n        self.assertEqual(vtt.captions[1].start, '00:00:11.378')\n        self.assertEqual(vtt.captions[1].end, '00:00:12.305')\n\n    def test_timestamps_in_seconds(self):\n        vtt = webvtt.from_sbv(PATH_TO_SAMPLES / 'sample.sbv')\n        self.assertEqual(vtt.captions[1].start_in_seconds, 11)\n        self.assertEqual(vtt.captions[1].end_in_seconds, 12)\n\n    def test_get_caption_text(self):\n        vtt = webvtt.from_sbv(PATH_TO_SAMPLES / 'sample.sbv')\n        self.assertEqual(vtt.captions[1].text, 'Caption text #2')\n\n    def test_get_caption_text_multiline(self):\n        vtt = webvtt.from_sbv(PATH_TO_SAMPLES / 'sample.sbv')\n        self.assertEqual(\n            vtt.captions[2].text,\n            'Caption text #3 (line 1)\\nCaption text #3 (line 2)'\n            )\n        self.assertListEqual(\n            vtt.captions[2].lines,\n            ['Caption text #3 (line 1)', 'Caption text #3 (line 2)']\n            )\n\n    def test_convert_from_srt_to_vtt_and_back_gives_same_file(self):\n        with tempfile.NamedTemporaryFile('w', suffix='.srt') as f:\n            webvtt.from_srt(\n                PATH_TO_SAMPLES / 'sample.srt'\n                ).save_as_srt(f.name)\n\n            self.assertEqual(\n                pathlib.Path(PATH_TO_SAMPLES / 'sample.srt').read_text(),\n                pathlib.Path(f.name).read_text()\n                )\n\n    def test_save_file_with_bom(self):\n        with tempfile.NamedTemporaryFile('r', suffix='.vtt') as f:\n            webvtt.read(\n                PATH_TO_SAMPLES / 'one_caption.vtt'\n                ).save(f.name, add_bom=True)\n            self.assertEqual(\n                f.read(),\n                textwrap.dedent(f'''\n                    {CODEC_BOMS['utf-8'].decode()}WEBVTT\n\n                    00:00:00.500 --> 00:00:07.000\n                    Caption text #1\n                    ''').strip() + '\\n'\n                )\n\n    def test_save_file_with_bom_keeps_bom(self):\n        with tempfile.NamedTemporaryFile('r', suffix='.vtt') as f:\n            webvtt.read(\n                PATH_TO_SAMPLES / 'captions_with_bom.vtt'\n            ).save(f.name)\n            self.assertEqual(\n                f.read(),\n                textwrap.dedent(f'''\n                    {CODEC_BOMS['utf-8'].decode()}WEBVTT\n\n                    00:00:00.500 --> 00:00:07.000\n                    Caption text #1\n\n                    00:00:07.000 --> 00:00:11.890\n                    Caption text #2\n\n                    00:00:11.890 --> 00:00:16.320\n                    Caption text #3\n\n                    00:00:16.320 --> 00:00:21.580\n                    Caption text #4\n                    ''').strip() + '\\n'\n                )\n\n    def test_save_file_with_bom_removes_bom_if_requested(self):\n        with tempfile.NamedTemporaryFile('r', suffix='.vtt') as f:\n            webvtt.read(\n                PATH_TO_SAMPLES / 'captions_with_bom.vtt'\n            ).save(f.name, add_bom=False)\n            self.assertEqual(\n                f.read(),\n                textwrap.dedent(f'''\n                    WEBVTT\n\n                    00:00:00.500 --> 00:00:07.000\n                    Caption text #1\n\n                    00:00:07.000 --> 00:00:11.890\n                    Caption text #2\n\n                    00:00:11.890 --> 00:00:16.320\n                    Caption text #3\n\n                    00:00:16.320 --> 00:00:21.580\n                    Caption text #4\n                    ''').strip() + '\\n'\n                )\n\n    def test_save_file_with_encoding(self):\n        with tempfile.NamedTemporaryFile('rb', suffix='.vtt') as f:\n            webvtt.read(\n                PATH_TO_SAMPLES / 'one_caption.vtt'\n            ).save(f.name,\n                   encoding='utf-32-le'\n                   )\n            self.assertEqual(\n                f.read().decode('utf-32-le'),\n                textwrap.dedent('''\n                    WEBVTT\n\n                    00:00:00.500 --> 00:00:07.000\n                    Caption text #1\n                    ''').strip() + '\\n'\n                )\n\n    def test_save_file_with_encoding_and_bom(self):\n        with tempfile.NamedTemporaryFile('rb', suffix='.vtt') as f:\n            webvtt.read(\n                PATH_TO_SAMPLES / 'one_caption.vtt'\n            ).save(f.name,\n                   encoding='utf-32-le',\n                   add_bom=True\n                   )\n            self.assertEqual(\n                f.read().decode('utf-32-le'),\n                textwrap.dedent(f'''\n                    {CODEC_BOMS['utf-32-le'].decode('utf-32-le')}WEBVTT\n\n                    00:00:00.500 --> 00:00:07.000\n                    Caption text #1\n                    ''').strip() + '\\n'\n                )\n\n    def test_save_new_file_utf_8_default_encoding_no_bom(self):\n        with tempfile.NamedTemporaryFile('r', suffix='.vtt') as f:\n            vtt = webvtt.WebVTT()\n            vtt.captions.append(\n                Caption(start='00:00:00.500',\n                        end='00:00:07.000',\n                        text='Caption text #1'\n                        )\n                )\n            vtt.save(f.name)\n            self.assertEqual(vtt.encoding, 'utf-8')\n            self.assertEqual(\n                f.read(),\n                textwrap.dedent(f'''\n                    WEBVTT\n\n                    00:00:00.500 --> 00:00:07.000\n                    Caption text #1\n                    ''').strip() + '\\n'\n                )\n\n    def test_save_new_file_utf_8_default_encoding_with_bom(self):\n        with tempfile.NamedTemporaryFile('r', suffix='.vtt') as f:\n            vtt = webvtt.WebVTT()\n            vtt.captions.append(\n                Caption(start='00:00:00.500',\n                        end='00:00:07.000',\n                        text='Caption text #1'\n                        )\n                )\n            vtt.save(f.name,\n                     add_bom=True\n                     )\n            self.assertEqual(vtt.encoding, 'utf-8')\n            self.assertEqual(\n                f.read(),\n                textwrap.dedent(f'''\n                    {CODEC_BOMS['utf-8'].decode()}WEBVTT\n\n                    00:00:00.500 --> 00:00:07.000\n                    Caption text #1\n                    ''').strip() + '\\n'\n                )\n\n    def test_iter_slice(self):\n        vtt = webvtt.read(\n                PATH_TO_SAMPLES / 'sample.vtt'\n                )\n        slice_of_captions = vtt.iter_slice(start='00:00:11.000',\n                                           end='00:00:27.000'\n                                           )\n        for expected_caption in (vtt.captions[2],\n                                 vtt.captions[3],\n                                 vtt.captions[4]\n                                 ):\n            self.assertIs(expected_caption, next(slice_of_captions))\n\n        with self.assertRaises(StopIteration):\n            next(slice_of_captions)\n\n    def test_iter_slice_no_start_time(self):\n        vtt = webvtt.read(\n                PATH_TO_SAMPLES / 'sample.vtt'\n                )\n        slice_of_captions = vtt.iter_slice(end='00:00:27.000')\n        for expected_caption in (vtt.captions[0],\n                                 vtt.captions[1],\n                                 vtt.captions[2],\n                                 vtt.captions[3],\n                                 vtt.captions[4]\n                                 ):\n            self.assertIs(expected_caption, next(slice_of_captions))\n\n        with self.assertRaises(StopIteration):\n            next(slice_of_captions)\n\n    def test_iter_slice_no_end_time(self):\n        vtt = webvtt.read(\n                PATH_TO_SAMPLES / 'sample.vtt'\n                )\n        slice_of_captions = vtt.iter_slice(start='00:00:47.000')\n        for expected_caption in (vtt.captions[11],\n                                 vtt.captions[12],\n                                 vtt.captions[13],\n                                 vtt.captions[14],\n                                 vtt.captions[15]\n                                 ):\n            self.assertIs(expected_caption, next(slice_of_captions))\n\n        with self.assertRaises(StopIteration):\n            next(slice_of_captions)\n"
  },
  {
    "path": "webvtt/__init__.py",
    "content": "\"\"\"Main webvtt package.\"\"\"\n\n__version__ = '0.5.1'\n__author__ = 'Alejandro Mendez'\n__author_email__ = 'amendez23@gmail.com'\n\nfrom .webvtt import WebVTT\nfrom . import segmenter\nfrom .models import Caption, Style  # noqa\n\n__all__ = ['WebVTT', 'Caption', 'Style']\n\nread = WebVTT.read\nread_buffer = WebVTT.read_buffer\nfrom_buffer = WebVTT.from_buffer\nfrom_srt = WebVTT.from_srt\nfrom_sbv = WebVTT.from_sbv\nfrom_string = WebVTT.from_string\nsegment = segmenter.segment\n"
  },
  {
    "path": "webvtt/cli.py",
    "content": "\"\"\"CLI module.\"\"\"\n\nimport argparse\nimport typing\n\nfrom . import segmenter\n\n\ndef main(argv: typing.Optional[typing.Sequence] = None):\n    \"\"\"\n    Segment WebVTT file from command line.\n\n    :param argv: command line arguments\n    \"\"\"\n    arguments = argparse.ArgumentParser(\n        description='Segment WebVTT files.'\n        )\n    arguments.add_argument(\n        'command',\n        choices=['segment'],\n        help='command to perform'\n        )\n    arguments.add_argument(\n        'file',\n        metavar='PATH',\n        help='WebVTT file'\n        )\n    arguments.add_argument(\n        '-o', '--output',\n        metavar='PATH',\n        help='output directory'\n        )\n    arguments.add_argument(\n        '-d', '--target-duration',\n        metavar='NUMBER',\n        type=int,\n        default=segmenter.DEFAULT_SECONDS,\n        help='target duration of each segment in seconds, default: 10'\n        )\n    arguments.add_argument(\n        '-m', '--mpegts',\n        metavar='NUMBER',\n        type=int,\n        default=segmenter.DEFAULT_MPEGTS,\n        help='presentation timestamp value, default: 900000'\n        )\n\n    args = arguments.parse_args(argv)\n\n    segmenter.segment(\n        args.file,\n        args.output,\n        args.target_duration,\n        args.mpegts\n        )\n\n\nif __name__ == '__main__':\n    main()  # pragma: no cover\n"
  },
  {
    "path": "webvtt/errors.py",
    "content": "\"\"\"Errors module.\"\"\"\n\n\nclass MalformedFileError(Exception):\n    \"\"\"File is not in the right format.\"\"\"\n\n\nclass MalformedCaptionError(Exception):\n    \"\"\"Caption not in the right format.\"\"\"\n\n\nclass MissingFilenameError(Exception):\n    \"\"\"Missing a filename when saving to disk.\"\"\"\n"
  },
  {
    "path": "webvtt/models.py",
    "content": "\"\"\"Models module.\"\"\"\n\nimport re\nimport typing\n\nfrom .errors import MalformedCaptionError\n\n\nclass Timestamp:\n    \"\"\"Representation of a timestamp.\"\"\"\n\n    PATTERN = re.compile(r'(?:(\\d{1,2}):)?(\\d{1,2}):(\\d{1,2})\\.(\\d{3})')\n\n    def __init__(\n            self,\n            hours: int = 0,\n            minutes: int = 0,\n            seconds: int = 0,\n            milliseconds: int = 0\n            ):\n        \"\"\"Initialize.\"\"\"\n        self.hours = hours\n        self.minutes = minutes\n        self.seconds = seconds\n        self.milliseconds = milliseconds\n\n    def __str__(self):\n        \"\"\"Return the string representation of the timestamp.\"\"\"\n        return (\n            f'{self.hours:02d}:{self.minutes:02d}:{self.seconds:02d}'\n            f'.{self.milliseconds:03d}'\n            )\n\n    def to_tuple(self) -> typing.Tuple[int, int, int, int]:\n        \"\"\"Return the timestamp in tuple form.\"\"\"\n        return self.hours, self.minutes, self.seconds, self.milliseconds\n\n    def __repr__(self):\n        \"\"\"Return the string representation of the caption.\"\"\"\n        return (f'<{self.__class__.__name__} '\n                f'hours={self.hours} '\n                f'minutes={self.minutes} '\n                f'seconds={self.seconds} '\n                f'milliseconds={self.milliseconds}>'\n                )\n\n    def __eq__(self, other):\n        \"\"\"Compare equality with other object.\"\"\"\n        return self.to_tuple() == other.to_tuple()\n\n    def __ne__(self, other):\n        \"\"\"Compare a not equality with other object.\"\"\"\n        return self.to_tuple() != other.to_tuple()\n\n    def __gt__(self, other):\n        \"\"\"Compare greater than with other object.\"\"\"\n        return self.to_tuple() > other.to_tuple()\n\n    def __lt__(self, other):\n        \"\"\"Compare less than with other object.\"\"\"\n        return self.to_tuple() < other.to_tuple()\n\n    def __ge__(self, other):\n        \"\"\"Compare greater or equal with other object.\"\"\"\n        return self.to_tuple() >= other.to_tuple()\n\n    def __le__(self, other):\n        \"\"\"Compare less or equal with other object.\"\"\"\n        return self.to_tuple() <= other.to_tuple()\n\n    @classmethod\n    def from_string(cls, value: str) -> 'Timestamp':\n        \"\"\"Return a `Timestamp` instance from a string value.\"\"\"\n        if type(value) is not str:\n            raise MalformedCaptionError(f'Invalid timestamp {value!r}')\n\n        match = re.match(cls.PATTERN, value)\n        if not match:\n            raise MalformedCaptionError(f'Invalid timestamp {value!r}')\n\n        hours = int(match.group(1) or 0)\n        minutes = int(match.group(2))\n        seconds = int(match.group(3))\n        milliseconds = int(match.group(4))\n\n        if minutes > 59 or seconds > 59:\n            raise MalformedCaptionError(f'Invalid timestamp {value!r}')\n\n        return cls(hours, minutes, seconds, milliseconds)\n\n    def in_seconds(self) -> int:\n        \"\"\"Return the timestamp in seconds.\"\"\"\n        return (self.hours * 3600 +\n                self.minutes * 60 +\n                self.seconds\n                )\n\n\nclass Caption:\n    \"\"\"Representation of a caption.\"\"\"\n\n    CUE_TEXT_TAGS = re.compile('<.*?>')\n    VOICE_SPAN_PATTERN = re.compile(r'<v(?:\\.\\w+)*\\s+([^>]+)>')\n\n    def __init__(self,\n                 start: typing.Optional[str] = None,\n                 end: typing.Optional[str] = None,\n                 text: typing.Optional[typing.Union[str,\n                                                    typing.Sequence[str]\n                                                    ]] = None,\n                 identifier: typing.Optional[str] = None\n                 ):\n        \"\"\"\n        Initialize.\n\n        :param start: start time of the caption\n        :param end: end time of the caption\n        :param text: the text of the caption\n        :param identifier: optional identifier\n        \"\"\"\n        text = text or []\n        self.start = start or '00:00:00.000'\n        self.end = end or '00:00:00.000'\n        self.identifier = identifier\n        self.lines = (text.splitlines()\n                      if isinstance(text, str)\n                      else\n                      list(text)\n                      )\n        self.comments: typing.List[str] = []\n\n    def __repr__(self):\n        \"\"\"Return the string representation of the caption.\"\"\"\n        cleaned_text = self.text.replace('\\n', '\\\\n')\n        return (f'<{self.__class__.__name__} '\n                f'start={self.start!r} '\n                f'end={self.end!r} '\n                f'text={cleaned_text!r} '\n                f'identifier={self.identifier!r}>'\n                )\n\n    def __str__(self):\n        \"\"\"Return a readable representation of the caption.\"\"\"\n        cleaned_text = self.text.replace('\\n', '\\\\n')\n        return f'{self.start} {self.end} {cleaned_text}'\n\n    def __eq__(self, other):\n        \"\"\"Compare equality with another object.\"\"\"\n        if not isinstance(other, type(self)):\n            return False\n\n        return (self.start == other.start and\n                self.end == other.end and\n                self.raw_text == other.raw_text and\n                self.identifier == other.identifier\n                )\n\n    @property\n    def start(self):\n        \"\"\"Return the start time of the caption.\"\"\"\n        return str(self.start_time)\n\n    @start.setter\n    def start(self, value: str):\n        \"\"\"Set the start time of the caption.\"\"\"\n        self.start_time = Timestamp.from_string(value)\n\n    @property\n    def end(self):\n        \"\"\"Return the end time of the caption.\"\"\"\n        return str(self.end_time)\n\n    @end.setter\n    def end(self, value: str):\n        \"\"\"Set the end time of the caption.\"\"\"\n        self.end_time = Timestamp.from_string(value)\n\n    @property\n    def start_in_seconds(self) -> int:\n        \"\"\"Return the start time of the caption in seconds.\"\"\"\n        return self.start_time.in_seconds()\n\n    @property\n    def end_in_seconds(self):\n        \"\"\"Return the end time of the caption in seconds.\"\"\"\n        return self.end_time.in_seconds()\n\n    @property\n    def raw_text(self) -> str:\n        \"\"\"Return the text of the caption (including cue tags).\"\"\"\n        return '\\n'.join(self.lines)\n\n    @property\n    def text(self) -> str:\n        \"\"\"Return the text of the caption (without cue tags).\"\"\"\n        return re.sub(self.CUE_TEXT_TAGS, '', self.raw_text)\n\n    @text.setter\n    def text(self, value: str):\n        \"\"\"Set the text of the captions.\"\"\"\n        if not isinstance(value, str):\n            raise AttributeError(\n                f'String value expected but received {value}.'\n                )\n\n        self.lines = value.splitlines()\n\n    @property\n    def voice(self) -> typing.Optional[str]:\n        \"\"\"Return the voice span if present.\"\"\"\n        if self.lines and self.lines[0].startswith('<v'):\n            match = re.match(self.VOICE_SPAN_PATTERN, self.lines[0])\n            if match:\n                return match.group(1)\n\n        return None\n\n\nclass Style:\n    \"\"\"Representation of a style.\"\"\"\n\n    def __init__(self, text: typing.Union[str, typing.List[str]]):\n        \"\"\"Initialize.\n\n        :param: text: the style text\n        \"\"\"\n        self.lines = text.splitlines() if isinstance(text, str) else text\n        self.comments: typing.List[str] = []\n\n    @property\n    def text(self):\n        \"\"\"Return the text of the style.\"\"\"\n        return '\\n'.join(self.lines)\n"
  },
  {
    "path": "webvtt/sbv.py",
    "content": "\"\"\"SBV format module.\"\"\"\n\nimport typing\nimport re\n\nfrom . import utils\nfrom .models import Caption\nfrom .errors import MalformedFileError\n\n\nclass SBVCueBlock:\n    \"\"\"Representation of a cue timing block.\"\"\"\n\n    CUE_TIMINGS_PATTERN = re.compile(\n        r'\\s*(\\d{1,2}:\\d{1,2}:\\d{1,2}.\\d{3}),(\\d{1,2}:\\d{1,2}:\\d{1,2}.\\d{3})'\n        )\n\n    def __init__(\n            self,\n            start: str,\n            end: str,\n            payload: typing.Sequence[str]\n            ):\n        \"\"\"\n        Initialize.\n\n        :param start: start time\n        :param end: end time\n        :param payload: caption text\n        \"\"\"\n        self.start = start\n        self.end = end\n        self.payload = payload\n\n    @classmethod\n    def is_valid(\n            cls,\n            lines: typing.Sequence[str]\n            ) -> bool:\n        \"\"\"\n        Validate the lines for a match of a cue time block.\n\n        :param lines: the lines to be validated\n        :returns: true for a matching cue time block\n        \"\"\"\n        return bool(\n          len(lines) >= 2 and\n          re.match(cls.CUE_TIMINGS_PATTERN, lines[0]) and\n          lines[1].strip()\n          )\n\n    @classmethod\n    def from_lines(\n            cls,\n            lines: typing.Sequence[str]\n            ) -> 'SBVCueBlock':\n        \"\"\"\n        Create a `SBVCueBlock` from lines of text.\n\n        :param lines: the lines of text\n        :returns: `SBVCueBlock` instance\n        \"\"\"\n        match = re.match(cls.CUE_TIMINGS_PATTERN, lines[0])\n        assert match is not None\n\n        payload = lines[1:]\n\n        return cls(match.group(1), match.group(2), payload)\n\n\ndef parse(lines: typing.Sequence[str]) -> typing.List[Caption]:\n    \"\"\"\n    Parse SBV captions from lines of text.\n\n    :param lines: lines of text\n    :returns: list of `Caption` objects\n    \"\"\"\n    if not _is_valid_content(lines):\n        raise MalformedFileError('Invalid format')\n\n    return _parse_captions(lines)\n\n\ndef _is_valid_content(lines: typing.Sequence[str]) -> bool:\n    \"\"\"\n    Validate lines of text for valid SBV content.\n\n    :param lines: lines of text\n    :returns: true for a valid SBV content\n    \"\"\"\n    if len(lines) < 2:\n        return False\n\n    first_block = next(utils.iter_blocks_of_lines(lines))\n    return bool(first_block and SBVCueBlock.is_valid(first_block))\n\n\ndef _parse_captions(lines: typing.Sequence[str]) -> typing.List[Caption]:\n    \"\"\"\n    Parse captions from the text.\n\n    :param lines: lines of text\n    :returns: list of `Caption` objects\n    \"\"\"\n    captions = []\n\n    for block_lines in utils.iter_blocks_of_lines(lines):\n        if not SBVCueBlock.is_valid(block_lines):\n            continue\n\n        cue_block = SBVCueBlock.from_lines(block_lines)\n        captions.append(Caption(cue_block.start,\n                                cue_block.end,\n                                cue_block.payload\n                                ))\n\n    return captions\n"
  },
  {
    "path": "webvtt/segmenter.py",
    "content": "\"\"\"Segmenter module.\"\"\"\n\nimport typing\nimport os\nimport pathlib\nfrom math import ceil, floor\n\nfrom .webvtt import WebVTT, Caption\n\nDEFAULT_MPEGTS = 900000\nDEFAULT_SECONDS = 10  # default number of seconds per segment\n\n\ndef segment(\n        webvtt_path: str,\n        output: str,\n        seconds: int = DEFAULT_SECONDS,\n        mpegts: int = DEFAULT_MPEGTS\n        ):\n    \"\"\"\n    Segment a WebVTT captions file.\n\n    :param webvtt_path: the path to the file\n    :param output: the path to the destination folder\n    :param seconds: the number of seconds for each segment\n    :param mpegts: value for the MPEG-TS\n    \"\"\"\n    captions = WebVTT.read(webvtt_path).captions\n\n    output_folder = pathlib.Path(output)\n    os.makedirs(output_folder, exist_ok=True)\n\n    segments = slice_segments(captions, seconds)\n    write_segments(output_folder, segments, mpegts)\n    write_manifest(output_folder, segments, seconds)\n\n\ndef slice_segments(\n        captions: typing.Sequence[Caption],\n        seconds: int\n        ) -> typing.List[typing.List[Caption]]:\n    \"\"\"\n    Slice segments of captions based on seconds per segment.\n\n    :param captions: the captions\n    :param seconds: seconds per segment\n    :returns: list of lists of `Caption` objects\n    \"\"\"\n    total_segments = (\n        0\n        if not captions else\n        int(ceil(captions[-1].end_in_seconds / seconds))\n    )\n\n    segments: typing.List[typing.List[Caption]] = [\n        [] for _ in range(total_segments)\n        ]\n\n    for c in captions:\n        segment_index_start = floor(c.start_in_seconds / seconds)\n        segments[segment_index_start].append(c)\n\n        # Also include a caption in other segments based on the end time.\n        segment_index_end = floor(c.end_in_seconds / seconds)\n        if segment_index_end > segment_index_start:\n            for i in range(segment_index_start + 1, segment_index_end + 1):\n                segments[i].append(c)\n\n    return segments\n\n\ndef write_segments(\n        output_folder: pathlib.Path,\n        segments: typing.Iterable[typing.Iterable[Caption]],\n        mpegts: int\n        ):\n    \"\"\"\n    Write the segments to the output folder.\n\n    :param output_folder: folder where the segment files will be stored\n    :param segments: the segments of `Caption` objects\n    :param mpegts: value for the MPEG-TS\n    \"\"\"\n    for index, segment in enumerate(segments):\n        segment_file = output_folder / f'fileSequence{index}.webvtt'\n\n        with open(segment_file, 'w', encoding='utf-8') as f:\n            f.write('WEBVTT\\n')\n            f.write(f'X-TIMESTAMP-MAP=MPEGTS:{mpegts},'\n                    'LOCAL:00:00:00.000\\n'\n                    )\n\n            for caption in segment:\n                f.write('\\n{} --> {}\\n'.format(caption.start, caption.end))\n                f.writelines(f'{line}\\n' for line in caption.lines)\n\n\ndef write_manifest(\n        output_folder: pathlib.Path,\n        segments: typing.Iterable[typing.Iterable[Caption]],\n        seconds: int\n        ):\n    \"\"\"\n    Write the manifest in the output folder.\n\n    :param output_folder: folder where the manifest will be stored\n    :param segments: the segments of `Caption` objects\n    :param seconds: the seconds per segment\n    \"\"\"\n    manifest_file = output_folder / 'prog_index.m3u8'\n    with open(manifest_file, 'w', encoding='utf-8') as f:\n        f.write('#EXTM3U\\n')\n        f.write(f'#EXT-X-TARGETDURATION:{seconds}\\n')\n        f.write('#EXT-X-VERSION:3\\n')\n        f.write('#EXT-X-PLAYLIST-TYPE:VOD\\n')\n\n        for index, _ in enumerate(segments):\n            f.write('#EXTINF:30.00000\\n')\n            f.write(f'fileSequence{index}.webvtt\\n')\n\n        f.write('#EXT-X-ENDLIST\\n')\n"
  },
  {
    "path": "webvtt/srt.py",
    "content": "\"\"\"SRT format module.\"\"\"\n\nimport typing\nimport re\n\nfrom .models import Caption\nfrom .errors import MalformedFileError\nfrom . import utils\n\n\nclass SRTCueBlock:\n    \"\"\"Representation of a cue timing block.\"\"\"\n\n    CUE_TIMINGS_PATTERN = re.compile(\n        r'\\s*(\\d+:\\d{2}:\\d{2},\\d{3})\\s*-->\\s*(\\d+:\\d{2}:\\d{2},\\d{3})'\n        )\n\n    def __init__(\n            self,\n            index: str,\n            start: str,\n            end: str,\n            payload: typing.Sequence[str]\n            ):\n        \"\"\"\n        Initialize.\n\n        :param start: start time\n        :param end: end time\n        :param payload: caption text\n        \"\"\"\n        self.index = index\n        self.start = start\n        self.end = end\n        self.payload = payload\n\n    @classmethod\n    def is_valid(\n            cls,\n            lines: typing.Sequence[str]\n            ) -> bool:\n        \"\"\"\n        Validate the lines for a match of a cue time block.\n\n        :param lines: the lines to be validated\n        :returns: true for a matching cue time block\n        \"\"\"\n        return bool(\n          len(lines) >= 3 and\n          lines[0].isdigit() and\n          re.match(cls.CUE_TIMINGS_PATTERN, lines[1])\n          )\n\n    @classmethod\n    def from_lines(\n            cls,\n            lines: typing.Sequence[str]\n            ) -> 'SRTCueBlock':\n        \"\"\"\n        Create a `SRTCueBlock` from lines of text.\n\n        :param lines: the lines of text\n        :returns: `SRTCueBlock` instance\n        \"\"\"\n        index = lines[0]\n\n        match = re.match(cls.CUE_TIMINGS_PATTERN, lines[1])\n        assert match is not None\n\n        payload = lines[2:]\n\n        return cls(index, match.group(1), match.group(2), payload)\n\n\ndef parse(lines: typing.Sequence[str]) -> typing.List[Caption]:\n    \"\"\"\n    Parse SRT captions from lines of text.\n\n    :param lines: lines of text\n    :returns: list of `Caption` objects\n    \"\"\"\n    if not is_valid_content(lines):\n        raise MalformedFileError('Invalid format')\n\n    return parse_captions(lines)\n\n\ndef is_valid_content(lines: typing.Sequence[str]) -> bool:\n    \"\"\"\n    Validate lines of text for valid SBV content.\n\n    :param lines: lines of text\n    :returns: true for a valid SBV content\n    \"\"\"\n    return bool(\n        len(lines) >= 3 and\n        lines[0].isdigit() and\n        '-->' in lines[1] and\n        lines[2].strip()\n    )\n\n\ndef parse_captions(lines: typing.Sequence[str]) -> typing.List[Caption]:\n    \"\"\"\n    Parse captions from the text.\n\n    :param lines: lines of text\n    :returns: list of `Caption` objects\n    \"\"\"\n    captions: typing.List[Caption] = []\n\n    for block_lines in utils.iter_blocks_of_lines(lines):\n        if not SRTCueBlock.is_valid(block_lines):\n            continue\n\n        cue_block = SRTCueBlock.from_lines(block_lines)\n        cue_block.start, cue_block.end = map(\n            lambda x: x.replace(',', '.'), (cue_block.start, cue_block.end))\n\n        captions.append(Caption(cue_block.start,\n                                cue_block.end,\n                                cue_block.payload\n                                ))\n\n    return captions\n\n\ndef write(\n        f: typing.IO[str],\n        captions: typing.Iterable[Caption]\n        ):\n    \"\"\"\n    Write captions to an output.\n\n    :param f: file or file-like object\n    :param captions: Iterable of `Caption` objects\n    \"\"\"\n    output = []\n    for index, caption in enumerate(captions, start=1):\n        output.extend([\n            f'{index}',\n            '{} --> {}'.format(*map(lambda x: x.replace('.', ','),\n                                    (caption.start, caption.end))\n                               ),\n            *caption.text.splitlines(),\n            ''\n            ])\n    f.write('\\n'.join(output).rstrip())\n"
  },
  {
    "path": "webvtt/utils.py",
    "content": "\"\"\"Utils module.\"\"\"\n\nimport typing\nimport codecs\n\nCODEC_BOMS = {\n    'utf-8': codecs.BOM_UTF8,\n    'utf-32-le': codecs.BOM_UTF32_LE,\n    'utf-32-be': codecs.BOM_UTF32_BE,\n    'utf-16-le': codecs.BOM_UTF16_LE,\n    'utf-16-be': codecs.BOM_UTF16_BE\n}\n\n\nclass FileWrapper:\n    \"\"\"File handling functionality with built-in support for Byte OrderMark.\"\"\"\n\n    def __init__(\n            self,\n            file_path: str,\n            mode: typing.Optional[str] = None,\n            encoding: typing.Optional[str] = None\n            ):\n        \"\"\"\n        Initialize.\n\n        :param file_path: path to the file\n        :param mode: mode in which the file is opened\n        :param encoding: name of the encoding used to decode the file\n        \"\"\"\n        self.file_path = file_path\n        self.mode = mode or 'r'\n        self.bom_encoding = self.detect_bom_encoding(file_path)\n        self.encoding = (self.bom_encoding or\n                         encoding or\n                         'utf-8'\n                         )\n\n    @classmethod\n    def open(\n            cls,\n            file_path: str,\n            mode: typing.Optional[str] = None,\n            encoding: typing.Optional[str] = None\n            ) -> 'FileWrapper':\n        \"\"\"\n        Open a file.\n\n        :param file_path: path to the file\n        :param mode: mode in which the file is opened\n        :param encoding: name of the encoding used to decode the file\n        \"\"\"\n        return cls(file_path, mode, encoding)\n\n    def __enter__(self):\n        \"\"\"Enter context.\"\"\"\n        self.file = open(\n            file=self.file_path,\n            mode=self.mode,\n            encoding=self.encoding\n            )\n        if self.bom_encoding:\n            self.file.seek(len(CODEC_BOMS[self.bom_encoding]))\n        return self\n\n    def __exit__(self, exc_type, exc_val, exc_tb):\n        \"\"\"Exit context.\"\"\"\n        self.file.close()\n\n    @staticmethod\n    def detect_bom_encoding(file_path: str) -> typing.Optional[str]:\n        \"\"\"\n        Detect the encoding of a file based on the presence of the BOM.\n\n        :param file_path: path to the file\n        :returns: the encoding if BOM is found or None.\n        \"\"\"\n        with open(file_path, mode='rb') as f:\n            first_bytes = f.read(4)\n            for encoding, bom in CODEC_BOMS.items():\n                if first_bytes.startswith(bom):\n                    return encoding\n        return None\n\n\ndef iter_blocks_of_lines(\n        lines: typing.Iterable[str]\n        ) -> typing.Generator[typing.List[str], None, None]:\n    \"\"\"\n    Iterate blocks of text.\n\n    :param lines: lines of text.\n    \"\"\"\n    current_text_block = []\n\n    for line in lines:\n        if line.strip():\n            current_text_block.append(line)\n        elif current_text_block:\n            yield current_text_block\n            current_text_block = []\n\n    if current_text_block:\n        yield current_text_block\n"
  },
  {
    "path": "webvtt/vtt.py",
    "content": "\"\"\"VTT format module.\"\"\"\n\nimport re\nimport typing\nfrom dataclasses import dataclass\n\nfrom .errors import MalformedFileError\nfrom .models import Caption, Style\nfrom . import utils\n\n\n@dataclass\nclass ParserOutput:\n    \"\"\"Output of parser.\"\"\"\n\n    styles: typing.List[Style]\n    captions: typing.List[Caption]\n    header_comments: typing.List[str]\n    footer_comments: typing.List[str]\n\n    @classmethod\n    def from_data(\n            cls,\n            data: typing.Mapping[str, typing.Any]\n            ) -> 'ParserOutput':\n        \"\"\"\n        Return a `ParserOutput` instance from the provided data.\n\n        :param data: data from the parser\n        :returns: an instance of `ParserOutput`\n        \"\"\"\n        items = data.get('items', [])\n        return cls(\n            captions=[it for it in items if isinstance(it, Caption)],\n            styles=[it for it in items if isinstance(it, Style)],\n            header_comments=data.get('header_comments', []),\n            footer_comments=data.get('footer_comments', [])\n            )\n\n\nclass WebVTTCueBlock:\n    \"\"\"Representation of a cue timing block.\"\"\"\n\n    CUE_TIMINGS_PATTERN = re.compile(\n        r'\\s*((?:\\d+:)?\\d{2}:\\d{2}.\\d{3})\\s*-->\\s*((?:\\d+:)?\\d{2}:\\d{2}.\\d{3})'\n        )\n\n    def __init__(\n            self,\n            identifier,\n            start,\n            end,\n            payload\n            ):\n        \"\"\"\n        Initialize.\n\n        :param start: start time\n        :param end: end time\n        :param payload: caption text\n        \"\"\"\n        self.identifier = identifier\n        self.start = start\n        self.end = end\n        self.payload = payload\n\n    @classmethod\n    def is_valid(\n            cls,\n            lines: typing.Sequence[str]\n            ) -> bool:\n        \"\"\"\n        Validate the lines for a match of a cue time block.\n\n        :param lines: the lines to be validated\n        :returns: true for a matching cue time block\n        \"\"\"\n        return bool(\n            (\n              len(lines) >= 2 and\n              re.match(cls.CUE_TIMINGS_PATTERN, lines[0]) and\n              \"-->\" not in lines[1]\n              ) or\n            (\n              len(lines) >= 3 and\n              \"-->\" not in lines[0] and\n              re.match(cls.CUE_TIMINGS_PATTERN, lines[1]) and\n              \"-->\" not in lines[2]\n              )\n        )\n\n    @classmethod\n    def from_lines(\n            cls,\n            lines: typing.Iterable[str]\n            ) -> 'WebVTTCueBlock':\n        \"\"\"\n        Create a `WebVTTCueBlock` from lines of text.\n\n        :param lines: the lines of text\n        :returns: `WebVTTCueBlock` instance\n        \"\"\"\n        identifier = None\n        start = None\n        end = None\n        payload = []\n\n        for line in lines:\n            timing_match = re.match(cls.CUE_TIMINGS_PATTERN, line)\n            if timing_match:\n                start = timing_match.group(1)\n                end = timing_match.group(2)\n            elif not start:\n                identifier = line\n            else:\n                payload.append(line)\n\n        return cls(identifier, start, end, payload)\n\n    @staticmethod\n    def format_lines(caption: Caption) -> typing.List[str]:\n        \"\"\"\n        Return the lines for a cue block.\n\n        :param caption: the `Caption` instance\n        :returns: list of lines for a cue block\n        \"\"\"\n        return [\n            '',\n            *(identifier for identifier in {caption.identifier} if identifier),\n            f'{caption.start} --> {caption.end}',\n            *caption.lines\n        ]\n\n\nclass WebVTTCommentBlock:\n    \"\"\"Representation of a comment block.\"\"\"\n\n    COMMENT_PATTERN = re.compile(r'NOTE\\s(.*?)\\Z', re.DOTALL)\n\n    def __init__(self, text: str):\n        \"\"\"\n        Initialize.\n\n        :param text: comment text\n        \"\"\"\n        self.text = text\n\n    @classmethod\n    def is_valid(\n            cls,\n            lines: typing.Sequence[str]\n            ) -> bool:\n        \"\"\"\n        Validate the lines for a match of a comment block.\n\n        :param lines: the lines to be validated\n        :returns: true for a matching comment block\n        \"\"\"\n        return bool(lines and lines[0].startswith('NOTE'))\n\n    @classmethod\n    def from_lines(\n            cls,\n            lines: typing.Iterable[str]\n            ) -> 'WebVTTCommentBlock':\n        \"\"\"\n        Create a `WebVTTCommentBlock` from lines of text.\n\n        :param lines: the lines of text\n        :returns: `WebVTTCommentBlock` instance\n        \"\"\"\n        match = cls.COMMENT_PATTERN.match('\\n'.join(lines))\n        return cls(text=match.group(1).strip() if match else '')\n\n    @staticmethod\n    def format_lines(lines: str) -> typing.List[str]:\n        \"\"\"\n        Return the lines for a comment block.\n\n        :param lines: comment lines\n        :returns: list of lines for a comment block\n        \"\"\"\n        list_of_lines = lines.split('\\n')\n\n        if len(list_of_lines) == 1:\n            return [f'NOTE {lines}']\n\n        return ['NOTE', *list_of_lines]\n\n\nclass WebVTTStyleBlock:\n    \"\"\"Representation of a style block.\"\"\"\n\n    STYLE_PATTERN = re.compile(r'STYLE\\s(.*?)\\Z', re.DOTALL)\n\n    def __init__(self, text: str):\n        \"\"\"\n        Initialize.\n\n        :param text: style text\n        \"\"\"\n        self.text = text\n\n    @classmethod\n    def is_valid(\n            cls,\n            lines: typing.Sequence[str]\n            ) -> bool:\n        \"\"\"\n        Validate the lines for a match of a style block.\n\n        :param lines: the lines to be validated\n        :returns: true for a matching style block\n        \"\"\"\n        return (len(lines) >= 2 and\n                lines[0] == 'STYLE' and\n                not any(line.strip() == '' or '-->' in line for line in lines)\n                )\n\n    @classmethod\n    def from_lines(\n            cls,\n            lines: typing.Iterable[str]\n            ) -> 'WebVTTStyleBlock':\n        \"\"\"\n        Create a `WebVTTStyleBlock` from lines of text.\n\n        :param lines: the lines of text\n        :returns: `WebVTTStyleBlock` instance\n        \"\"\"\n        match = cls.STYLE_PATTERN.match('\\n'.join(lines))\n        return cls(text=match.group(1).strip() if match else '')\n\n    @staticmethod\n    def format_lines(lines: typing.List[str]) -> typing.List[str]:\n        \"\"\"\n        Return the lines for a style block.\n\n        :param lines: style lines\n        :returns: list of lines for a style block\n        \"\"\"\n        return ['STYLE', *lines]\n\n\ndef parse(\n        lines: typing.Sequence[str]\n        ) -> ParserOutput:\n    \"\"\"\n    Parse VTT captions from lines of text.\n\n    :param lines: lines of text\n    :returns: object `ParserOutput` with all parsed items\n    \"\"\"\n    if not is_valid_content(lines):\n        raise MalformedFileError('Invalid format')\n\n    return parse_items(lines)\n\n\ndef is_valid_content(lines: typing.Sequence[str]) -> bool:\n    \"\"\"\n    Validate lines of text for valid VTT content.\n\n    :param lines: lines of text\n    :returns: true for a valid VTT content\n    \"\"\"\n    return bool(lines and lines[0].startswith('WEBVTT'))\n\n\ndef parse_items(\n        lines: typing.Sequence[str]\n        ) -> ParserOutput:\n    \"\"\"\n    Parse items from the text.\n\n    :param lines: lines of text\n    :returns: an object `ParserOutput` with all parsed items\n    \"\"\"\n    header_comments: typing.List[str] = []\n    items: typing.List[typing.Union[Caption, Style]] = []\n    comments: typing.List[WebVTTCommentBlock] = []\n\n    for block_lines in utils.iter_blocks_of_lines(lines):\n        item = parse_item(block_lines)\n        if item:\n            item.comments = [comment.text for comment in comments]\n            comments = []\n            items.append(item)\n        elif WebVTTCommentBlock.is_valid(block_lines):\n            comments.append(WebVTTCommentBlock.from_lines(block_lines))\n\n    if items:\n        header_comments, items[0].comments = items[0].comments, header_comments\n\n    return ParserOutput.from_data(\n        {'items': items,\n         'header_comments': header_comments,\n         'footer_comments': [comment.text for comment in comments]\n         }\n        )\n\n\ndef parse_item(\n        lines: typing.Sequence[str]\n        ) -> typing.Union[Caption, Style, None]:\n    \"\"\"\n    Parse an item from lines of text.\n\n    :param lines: lines of text\n    :returns: An item (Caption or Style) if found, otherwise None\n    \"\"\"\n    if WebVTTCueBlock.is_valid(lines):\n        cue_block = WebVTTCueBlock.from_lines(lines)\n        return Caption(cue_block.start,\n                       cue_block.end,\n                       cue_block.payload,\n                       cue_block.identifier\n                       )\n\n    if WebVTTStyleBlock.is_valid(lines):\n        return Style(WebVTTStyleBlock.from_lines(lines).text)\n\n    return None\n\n\ndef write(\n        f: typing.IO[str],\n        captions: typing.Iterable[Caption],\n        styles: typing.Iterable[Style],\n        header_comments: typing.Iterable[str],\n        footer_comments: typing.Iterable[str]\n        ):\n    \"\"\"\n    Write captions to an output.\n\n    :param f: file or file-like object\n    :param captions: Iterable of `Caption` objects\n    :param styles: Iterable of `Style` objects\n    :param header_comments: the comments for the header\n    :param footer_comments: the comments for the footer\n    \"\"\"\n    f.write(\n        to_str(captions,\n               styles,\n               header_comments,\n               footer_comments\n               )\n        )\n\n\ndef to_str(\n        captions: typing.Iterable[Caption],\n        styles: typing.Iterable[Style],\n        header_comments: typing.Iterable[str],\n        footer_comments: typing.Iterable[str]\n        ) -> str:\n    \"\"\"\n    Convert captions to a string with webvtt format.\n\n    :param captions: the iterable of `Caption` objects\n    :param styles: the iterable of `Style` objects\n    :param header_comments: the comments for the header\n    :param footer_comments: the comments for the footer\n    :returns: String of the content in WebVTT format.\n    \"\"\"\n    output = ['WEBVTT']\n\n    for comment in header_comments:\n        output.extend([\n            '',\n            *WebVTTCommentBlock.format_lines(comment)\n        ])\n\n    for style in styles:\n        for comment in style.comments:\n            output.extend([\n                '',\n                *WebVTTCommentBlock.format_lines(comment)\n            ])\n        output.extend([\n            '',\n            *WebVTTStyleBlock.format_lines(style.lines)\n            ])\n\n    for caption in captions:\n        for comment in caption.comments:\n            output.extend([\n                '',\n                *WebVTTCommentBlock.format_lines(comment)\n            ])\n        output.extend(WebVTTCueBlock.format_lines(caption))\n\n    if not footer_comments:\n        output.append('')\n\n    for comment in footer_comments:\n        output.extend([\n            '',\n            *WebVTTCommentBlock.format_lines(comment)\n        ])\n\n    return '\\n'.join(output)\n"
  },
  {
    "path": "webvtt/webvtt.py",
    "content": "\"\"\"WebVTT module.\"\"\"\n\nimport os\nimport io\nimport typing\nimport warnings\nfrom functools import partial\n\nfrom . import vtt, utils\nfrom . import srt\nfrom . import sbv\nfrom .models import Caption, Style, Timestamp\nfrom .errors import MissingFilenameError\n\nDEFAULT_ENCODING = 'utf-8'\n\n\nclass WebVTT:\n    \"\"\"\n    Parse captions in WebVTT format and also from other formats like SRT.\n\n    To read WebVTT:\n\n        WebVTT.read('captions.vtt')\n\n    For other formats:\n\n        WebVTT.from_srt('captions.srt')\n        WebVTT.from_sbv('captions.sbv')\n    \"\"\"\n\n    def __init__(\n            self,\n            file: typing.Optional[str] = None,\n            captions: typing.Optional[typing.List[Caption]] = None,\n            styles: typing.Optional[typing.List[Style]] = None,\n            header_comments: typing.Optional[typing.List[str]] = None,\n            footer_comments: typing.Optional[typing.List[str]] = None,\n            ):\n        \"\"\"\n        Initialize.\n\n        :param file: the path of the WebVTT file\n        :param captions: the list of captions\n        :param styles: the list of styles\n        :param header_comments: list of comments for the start of the file\n        :param footer_comments: list of comments for the bottom of the file\n        \"\"\"\n        self.file = file\n        self.captions = captions or []\n        self.styles = styles or []\n        self.header_comments = header_comments or []\n        self.footer_comments = footer_comments or []\n        self._has_bom = False\n        self.encoding = DEFAULT_ENCODING\n\n    def __len__(self):\n        \"\"\"Return the number of captions.\"\"\"\n        return len(self.captions)\n\n    def __getitem__(self, index):\n        \"\"\"Return a caption by index.\"\"\"\n        return self.captions[index]\n\n    def __repr__(self):\n        \"\"\"Return the string representation of the WebVTT file.\"\"\"\n        return (f'<{self.__class__.__name__} file={self.file!r} '\n                f'encoding={self.encoding!r}>'\n                )\n\n    def __str__(self):\n        \"\"\"Return a readable representation of the WebVTT content.\"\"\"\n        return '\\n'.join(str(c) for c in self.captions)\n\n    @classmethod\n    def read(\n            cls,\n            file: str,\n            encoding: typing.Optional[str] = None\n            ) -> 'WebVTT':\n        \"\"\"\n        Read a WebVTT captions file.\n\n        :param file: the file path\n        :param encoding: encoding of the file\n        :returns: a `WebVTT` instance\n        \"\"\"\n        with utils.FileWrapper.open(file, encoding=encoding) as fw:\n            instance = cls.from_buffer(fw.file)\n            if fw.bom_encoding:\n                instance.encoding = fw.bom_encoding\n                instance._has_bom = True\n            return instance\n\n    @classmethod\n    def read_buffer(\n            cls,\n            buffer: typing.Iterator[str]\n            ) -> 'WebVTT':\n        \"\"\"\n        Read WebVTT captions from a file-like object.\n\n        This method is DEPRECATED. Use from_buffer instead.\n\n        Such file-like object may be the return of an io.open call,\n        io.StringIO object, tempfile.TemporaryFile object, etc.\n\n        :param buffer: the file-like object to read captions from\n        :returns: a `WebVTT` instance\n        \"\"\"\n        warnings.warn(\n            'Deprecated: use from_buffer instead.',\n            DeprecationWarning\n            )\n        return cls.from_buffer(buffer)\n\n    @classmethod\n    def from_buffer(\n            cls,\n            buffer: typing.Union[typing.Iterable[str], io.BytesIO],\n            format: str = 'vtt'\n            ) -> 'WebVTT':\n        \"\"\"\n        Read WebVTT captions from a file-like object.\n\n        Such file-like object may be the return of an io.open call,\n        io.StringIO object, tempfile.TemporaryFile object, etc.\n\n        :param buffer: the file-like object to read captions from\n        :param format: the format of the data (vtt, srt or sbv)\n        :returns: a `WebVTT` instance\n        \"\"\"\n        if isinstance(buffer, io.BytesIO):\n            buffer = (line.decode('utf-8') for line in buffer)\n\n        _cls = partial(cls, file=getattr(buffer, 'name', None))\n\n        if format == 'vtt':\n            output = vtt.parse(cls._get_lines(buffer))\n\n            return _cls(\n                captions=output.captions,\n                styles=output.styles,\n                header_comments=output.header_comments,\n                footer_comments=output.footer_comments\n                )\n\n        if format == 'srt':\n            return _cls(\n                captions=srt.parse(cls._get_lines(buffer))\n                )\n\n        if format == 'sbv':\n            return _cls(\n                captions=sbv.parse(cls._get_lines(buffer))\n                )\n\n        raise ValueError(f'Format {format} is not supported.')\n\n    @classmethod\n    def from_srt(\n            cls,\n            file: str,\n            encoding: typing.Optional[str] = None\n            ) -> 'WebVTT':\n        \"\"\"\n        Read captions from a file in SubRip format.\n\n        :param file: the file path\n        :param encoding: encoding of the file\n        :returns: a `WebVTT` instance\n        \"\"\"\n        with utils.FileWrapper.open(file, encoding=encoding) as fw:\n            return cls(\n                file=fw.file.name,\n                captions=srt.parse(cls._get_lines(fw.file))\n                )\n\n    @classmethod\n    def from_sbv(\n            cls,\n            file: str,\n            encoding: typing.Optional[str] = None\n            ) -> 'WebVTT':\n        \"\"\"\n        Read captions from a file in YouTube SBV format.\n\n        :param file: the file path\n        :param encoding: encoding of the file\n        :returns: a `WebVTT` instance\n        \"\"\"\n        with utils.FileWrapper.open(file, encoding=encoding) as fw:\n            return cls(\n                file=fw.file.name,\n                captions=sbv.parse(cls._get_lines(fw.file)),\n                )\n\n    @classmethod\n    def from_string(cls, string: str) -> 'WebVTT':\n        \"\"\"\n        Read captions from a string.\n\n        :param string: the captions in a string\n        :returns: a `WebVTT` instance\n        \"\"\"\n        output = vtt.parse(cls._get_lines(string.splitlines()))\n        return cls(\n            captions=output.captions,\n            styles=output.styles,\n            header_comments=output.header_comments,\n            footer_comments=output.footer_comments\n        )\n\n    @staticmethod\n    def _get_lines(lines: typing.Iterable[str]) -> typing.List[str]:\n        \"\"\"\n        Return cleaned lines from an iterable of lines.\n\n        :param lines: iterable of lines\n        :returns: a list of cleaned lines\n        \"\"\"\n        return [line.rstrip('\\n\\r') for line in lines]\n\n    def _get_destination_file(\n            self,\n            destination_path: typing.Optional[str] = None,\n            extension: str = 'vtt'\n            ) -> str:\n        \"\"\"\n        Return the destination file based on the provided params.\n\n        :param destination_path: optional destination path\n        :param extension: the extension of the file\n        :returns: the destination file\n\n        :raises MissingFilenameError: if destination path cannot be determined\n        \"\"\"\n        if not destination_path and not self.file:\n            raise MissingFilenameError\n\n        if not destination_path and self.file:\n            destination_path = (\n                f'{os.path.splitext(self.file)[0]}.{extension}'\n                )\n\n        assert destination_path is not None\n\n        target = os.path.join(os.getcwd(), destination_path)\n        if os.path.isdir(target):\n            if not self.file:\n                raise MissingFilenameError\n\n            # store the file in specified directory\n            base_name = os.path.splitext(os.path.basename(self.file))[0]\n            new_filename = f'{base_name}.{extension}'\n            return os.path.join(target, new_filename)\n\n        if target[-4:].lower() != f'.{extension}':\n            target = f'{target}.{extension}'\n\n        # store the file in the specified full path\n        return target\n\n    def save(\n            self,\n            output: typing.Optional[str] = None,\n            encoding: typing.Optional[str] = None,\n            add_bom: typing.Optional[bool] = None\n            ):\n        \"\"\"\n        Save the WebVTT captions to a file.\n\n        :param output: destination path of the file\n        :param encoding: encoding of the file\n        :param add_bom: save the file with Byte Order Mark\n\n        :raises MissingFilenameError: if output cannot be determined\n        \"\"\"\n        self.file = self._get_destination_file(output)\n        encoding = encoding or self.encoding\n\n        if add_bom is None and self._has_bom:\n            add_bom = True\n\n        with open(self.file, 'w', encoding=encoding) as f:\n            if add_bom and encoding in utils.CODEC_BOMS:\n                f.write(utils.CODEC_BOMS[encoding].decode(encoding))\n\n            vtt.write(\n                f,\n                self.captions,\n                self.styles,\n                self.header_comments,\n                self.footer_comments\n                )\n\n    def save_as_srt(\n            self,\n            output: typing.Optional[str] = None,\n            encoding: typing.Optional[str] = DEFAULT_ENCODING\n            ):\n        \"\"\"\n        Save the WebVTT captions to a file in SubRip format.\n\n        :param output: destination path of the file\n        :param encoding: encoding of the file\n\n        :raises MissingFilenameError: if output cannot be determined\n        \"\"\"\n        self.file = self._get_destination_file(output, extension='srt')\n        with open(self.file, 'w', encoding=encoding) as f:\n            srt.write(f, self.captions)\n\n    def write(\n            self,\n            f: typing.IO[str],\n            format: str = 'vtt'\n            ):\n        \"\"\"\n        Save the WebVTT captions to a file-like object.\n\n        :param f: destination file-like object\n        :param format: the format to use (`vtt` or `srt`)\n\n        :raises MissingFilenameError: if output cannot be determined\n        \"\"\"\n        if format == 'vtt':\n            return vtt.write(f,\n                             self.captions,\n                             self.styles,\n                             self.header_comments,\n                             self.footer_comments\n                             )\n        if format == 'srt':\n            return srt.write(f, self.captions)\n\n        raise ValueError(f'Format {format} is not supported.')\n\n    def iter_slice(\n            self,\n            start: typing.Optional[str] = None,\n            end: typing.Optional[str] = None\n            ) -> typing.Generator[Caption, None, None]:\n        \"\"\"\n        Iterate a slice of the captions based on a time range.\n\n        :param start: start timestamp of the range\n        :param end: end timestamp of the range\n        :returns: generator of Captions\n        \"\"\"\n        start_time = Timestamp.from_string(start) if start else None\n        end_time = Timestamp.from_string(end) if end else None\n\n        for caption in self.captions:\n            if (\n                    (not start_time or caption.start_time >= start_time) and\n                    (not end_time or caption.end_time <= end_time)\n                    ):\n                yield caption\n\n    @property\n    def total_length(self):\n        \"\"\"Returns the total length of the captions.\"\"\"\n        if not self.captions:\n            return 0\n        return (\n                self.captions[-1].end_in_seconds -\n                self.captions[0].start_in_seconds\n                )\n\n    @property\n    def content(self) -> str:\n        \"\"\"\n        Return the webvtt capions as string.\n\n        This property is useful in cases where the webvtt content is needed\n        but no file-like destination is required. Storage in DB for instance.\n        \"\"\"\n        return vtt.to_str(\n            self.captions,\n            self.styles,\n            self.header_comments,\n            self.footer_comments\n            )\n"
  }
]