Repository: Zulko/moviepy
Pull request #1837 (2022-10-07 11:31:01)

Handle brackets and language in FFMPEG output
After #1781 we capture whatever is in square brackets as language. Newer ffmpeg versions can provide both the value in square brackets (whatever that is) and language in parenthesis, which breaks the regex.
I changed the regex to ignore the value in square brackets (using non-capturing group) and always get the language from the parenthesis.
All previous tests pass without changing, so I assume backwards compatibility is intact.

- [x] I have provided code that clearly demonstrates the bug and that only works correctly when applying this fix
- [x] I have added suitable tests demonstrating a fixed bug or new/changed feature to the test suite in `tests/`
- [x] I have properly documented new or changed features in the documentation or in the docstrings
- [x] I have properly explained unusual or unexpected code in the comments around it


coveralls: 
[![Coverage Status](https://coveralls.io/builds/53098482/badge)](https://coveralls.io/builds/53098482)

Coverage decreased (-3.1%) to 81.751% when pulling **a5d2245d17fc8014025ec40bc78414c4315abc5a on TraseeHQ:fix-square-brackets-and-language** into **18e9f57d1abbae8051b9aef75de3f19b4d1f0630 on Zulko:master**.


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 995d3e6..423c2ec 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -64,6 +64,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 - Fixed scroll FX not being scrolling [\#1591](https://github.com/Zulko/moviepy/pull/1591)
 - Fixed parsing FFMPEG streams with square brackets [\#1781](https://github.com/Zulko/moviepy/pull/1781)
 - Fixed audio processing for streams with missing `audio_bitrate` [\#1783](https://github.com/Zulko/moviepy/pull/1783)
+- Fixed parsing language from stream output with square brackets [\#1837](https://github.com/Zulko/moviepy/pull/1837)
 
 
 ## [v2.0.0.dev2](https://github.com/zulko/moviepy/tree/v2.0.0.dev2) (2020-10-05)
diff --git a/examples/moving_letters.py b/examples/moving_letters.py
index ece4220..19c85b2 100644
--- a/examples/moving_letters.py
+++ b/examples/moving_letters.py
@@ -61,7 +61,7 @@ letters = find_objects(cvc)  # a list of ImageClips
 
 def moveLetters(letters, funcpos):  # noqa D103
     return [
-        letter.set_pos(funcpos(letter.screenpos, i, len(letters)))
+        letter.with_position(funcpos(letter.screenpos, i, len(letters)))
         for i, letter in enumerate(letters)
     ]
 
diff --git a/moviepy/video/io/ffmpeg_reader.py b/moviepy/video/io/ffmpeg_reader.py
index c94e058..616deff 100644
--- a/moviepy/video/io/ffmpeg_reader.py
+++ b/moviepy/video/io/ffmpeg_reader.py
@@ -422,7 +422,8 @@ class FFmpegInfosParser:
 
                 # get input number, stream number, language and type
                 main_info_match = re.search(
-                    r"^Stream\s#(\d+):(\d+)[\[(]?(\w+)?[\])]?:\s(\w+):", line.lstrip()
+                    r"^Stream\s#(\d+):(\d+)(?:\[\w+\])?\(?(\w+)?\)?:\s(\w+):",
+                    line.lstrip(),
                 )
                 (
                     input_number,
@@ -434,9 +435,8 @@ class FFmpegInfosParser:
                 stream_number = int(stream_number)
                 stream_type_lower = stream_type.lower()
 
-                if language is not None:
-                    if language == "und" or language.startswith("0x"):
-                        language = None
+                if language == "und":
+                    language = None
 
                 # start builiding the current stream
                 self._current_stream = {


Test patch:
diff --git a/tests/test_ffmpeg_reader.py b/tests/test_ffmpeg_reader.py
index fad0507..e566bc5 100644
--- a/tests/test_ffmpeg_reader.py
+++ b/tests/test_ffmpeg_reader.py
@@ -527,6 +527,22 @@ At least one output file must be specified"""
     assert d["inputs"][0]["streams"][1]["language"] is None
 
 
+def test_stream_square_brackets_and_language():
+    infos = """
+Input #0, mpeg, from 'clip.mp4':
+  Duration: 00:02:15.00, start: 52874.498178, bitrate: 266 kb/s
+    Stream #0:0[0x1e0](eng): Video: ..., 25 tbr, 90k tbn, 50 tbc
+    Stream #0:1[0x1c0](und): Audio: mp2, 0 channels, s16p
+At least one output file must be specified"""
+
+    d = FFmpegInfosParser(infos, "clip.mp4").parse()
+
+    assert d
+    assert len(d["inputs"][0]["streams"]) == 2
+    assert d["inputs"][0]["streams"][0]["language"] == "eng"
+    assert d["inputs"][0]["streams"][1]["language"] is None
+
+
 def test_stream_missing_audio_bitrate():
     infos = """
 Input #0, mpeg, from 'clip.mp4':