Add areena.yle.fi video download support
diff --git a/yt_dlp/extractor/_extractors.py b/yt_dlp/extractor/_extractors.py
index 8652ec54e55..12218a55c48 100644
--- a/yt_dlp/extractor/_extractors.py
+++ b/yt_dlp/extractor/_extractors.py
@@ -2233,6 +2233,7 @@
 from .yapfiles import YapFilesIE
 from .yesjapan import YesJapanIE
 from .yinyuetai import YinYueTaiIE
+from .yle_areena import YleAreenaIE
 from .ynet import YnetIE
 from .youjizz import YouJizzIE
 from .youku import (
diff --git a/yt_dlp/extractor/yle_areena.py b/yt_dlp/extractor/yle_areena.py
new file mode 100644
index 00000000000..118dc1262d1
--- /dev/null
+++ b/yt_dlp/extractor/yle_areena.py
@@ -0,0 +1,71 @@
+from .common import InfoExtractor
+from .kaltura import KalturaIE
+from ..utils import int_or_none, traverse_obj, url_or_none
+
+
+class YleAreenaIE(InfoExtractor):
+    _VALID_URL = r'https?://areena\.yle\.fi/(?P<id>[\d-]+)'
+    _TESTS = [{
+        'url': 'https://areena.yle.fi/1-4371942',
+        'md5': '932edda0ecf5dfd6423804182d32f8ac',
+        'info_dict': {
+            'id': '0_a3tjk92c',
+            'ext': 'mp4',
+            'title': 'Pouchit',
+            'description': 'md5:d487309c3abbe5650265bbd1742d2f82',
+            'series': 'Modernit miehet',
+            'season': 'Season 1',
+            'season_number': 1,
+            'episode': 'Episode 2',
+            'episode_number': 2,
+            'thumbnail': 'http://cfvod.kaltura.com/p/1955031/sp/195503100/thumbnail/entry_id/0_a3tjk92c/version/100061',
+            'uploader_id': 'ovp@yle.fi',
+            'duration': 1435,
+            'view_count': int,
+            'upload_date': '20181204',
+            'timestamp': 1543916210,
+            'subtitles': {'fin': [{'url': r're:^https?://', 'ext': 'srt'}]},
+            'age_limit': 7,
+        }
+    }]
+
+    def _real_extract(self, url):
+        video_id = self._match_id(url)
+        info = self._search_json_ld(self._download_webpage(url, video_id), video_id, default={})
+        video_data = self._download_json(
+            f'https://player.api.yle.fi/v1/preview/{video_id}.json?app_id=player_static_prod&app_key=8930d72170e48303cf5f3867780d549b',
+            video_id)
+
+        # Example title: 'K1, J2: Pouchit | Modernit miehet'
+        series, season_number, episode_number, episode = self._search_regex(
+            r'K(?P<season_no>[\d]+),\s*J(?P<episode_no>[\d]+):?\s*\b(?P<episode>[^|]+)\s*|\s*(?P<series>.+)',
+            info.get('title') or '', 'episode metadata', group=('season_no', 'episode_no', 'episode', 'series'),
+            default=(None, None, None, None))
+        description = traverse_obj(video_data, ('data', 'ongoing_ondemand', 'description', 'fin'), expected_type=str)
+
+        subtitles = {}
+        for sub in traverse_obj(video_data, ('data', 'ongoing_ondemand', 'subtitles', ...)):
+            if url_or_none(sub.get('uri')):
+                subtitles.setdefault(sub.get('language') or 'und', []).append({
+                    'url': sub['uri'],
+                    'ext': 'srt',
+                    'name': sub.get('kind'),
+                })
+
+        return {
+            '_type': 'url_transparent',
+            'url': 'kaltura:1955031:%s' % traverse_obj(video_data, ('data', 'ongoing_ondemand', 'kaltura', 'id')),
+            'ie_key': KalturaIE.ie_key(),
+            'title': (traverse_obj(video_data, ('data', 'ongoing_ondemand', 'title', 'fin'), expected_type=str)
+                      or episode or info.get('title')),
+            'description': description,
+            'series': (traverse_obj(video_data, ('data', 'ongoing_ondemand', 'series', 'title', 'fin'), expected_type=str)
+                       or series),
+            'season_number': (int_or_none(self._search_regex(r'Kausi (\d+)', description, 'season number', default=None))
+                              or int(season_number)),
+            'episode_number': (traverse_obj(video_data, ('data', 'ongoing_ondemand', 'episode_number'), expected_type=int_or_none)
+                               or int(episode_number)),
+            'thumbnails': traverse_obj(info, ('thumbnails', ..., {'url': 'url'})),
+            'age_limit': traverse_obj(video_data, ('data', 'ongoing_ondemand', 'content_rating', 'age_restriction'), expected_type=int_or_none),
+            'subtitles': subtitles,
+        }

**IMPORTANT**: PRs without the template will be CLOSED

### Description of your *pull request* and other information

</details>

<!--

Explanation of your *pull request* in arbitrary form goes here. Please **make sure the description explains the purpose and effect** of your *pull request* and is worded well enough to be understood. Provide as much **context and examples** as possible

-->

Added new extractor for single videos from areena.yle.fi and corresponding test.

Fixes #2508


<details open><summary>Template</summary> <!-- OPEN is intentional -->

<!--

# PLEASE FOLLOW THE GUIDE BELOW

- You will be asked some questions, please read them **carefully** and answer honestly
- Put an `x` into all the boxes `[ ]` relevant to your *pull request* (like [x])
- Use *Preview* tab to see how your *pull request* will actually look like

-->

### Before submitting a *pull request* make sure you have:
- [x] At least skimmed through [contributing guidelines](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#developer-instructions) including [yt-dlp coding conventions](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#yt-dlp-coding-conventions)
- [x] [Searched](https://github.com/yt-dlp/yt-dlp/search?q=is%3Apr&type=Issues) the bugtracker for similar pull requests
- [x] Checked the code with [flake8](https://pypi.python.org/pypi/flake8) and [ran relevant tests](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#developer-instructions)

### In order to be accepted and merged into yt-dlp each piece of code must be in public domain or released under [Unlicense](http://unlicense.org/). Check one of the following options:
- [x] I am the original author of this code and I am willing to release it under [Unlicense](http://unlicense.org/)
- [ ] I am not the original author of this code but it is in public domain or released under [Unlicense](http://unlicense.org/) (provide reliable evidence)

### What is the purpose of your *pull request*?
- [ ] Fix or improvement to an extractor (Make sure to add/update tests)
- [x] New extractor ([Piracy websites will not be accepted](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#is-the-website-primarily-used-for-piracy))
- [ ] Core bug fix/improvement
- [ ] New feature (It is strongly [recommended to open an issue first](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#adding-new-feature-or-making-overarching-changes))
