Deprecation notice: The API endpoints mentioned in this tutorial will be disabled during the spring 2021.
Playing a program
Information needed to complete the steps in this tutorial:
app_id
andapp_key
credentials (you should’ve received these by email)- Media URL decryption secret - this should also be in your email
- Programs: bash, curl, python, QuickTime
Step 1: Get program details by ID
First, we must find a program we want to watch or listen. To do this, use YLE Areena to find a program you like. For this little tutorial, we’ve chosen this episode to act as an example. Then, grab the ID from the URL - it’s the part that looks like 1-XXXXXXX
. In our example, it’s 1-820561
Unfortunately at the moment we've had to limit access to some content (most notably DRM protected content). If you're having problems completing this tutorial, please try again with different program. Also see documentation on detecting media's availability.
Now, let’s make our first API request to retrieve the program details:
curl -v "https://external.api.yle.fi/v1/programs/items/1-820561.json?app_id=YOUR_APP_ID&app_key=YOUR_APP_KEY" \
| python -mjson.tool
If this produced an error, please make sure that you actually got an active program ID from Areena, as described at Step 1.
Okay, yes, that’s quite large wall of text you have in front of you. No need to get scared, though. What’s important here for our purposes are the publication events. Programs come and go. Sometimes, a program might be available for a month and is then removed from Areena. After a year the same program might get published again. We store a new publication event each time a program is published.
Step 2: Finding the correct publication event
You can get the publication event history from the program’s publicationEvent
array. This array contains all publication events the program has had, but for now, you should be concentrating only on the one with following properties:
temporalStatus == "currently" and type == "OnDemandPublication"
NOTE: (ScheduledTransmission type means the program is consumable from a TV or radio channel at the specified time.)
When these conditions match, it means the program is available from Areena and it’s media can be retrieved for watching.
In our example, the available publication event looks like this:
{
"id": "4-4359156",
"temporalStatus": "currently",
"type": "OnDemandPublication",
"startTime": "2015-04-28T10:00:00+03:00",
"endTime": "2020-04-30T23:59:59+03:00",
"region": "Finland",
"duration": "P5Y2DT13H59M59S",
"media": {
"downloadable": false,
"type": "VideoObject",
"available": true,
"contentProtection": [
{
"type": "ContentProtectionPolicy",
"id": "22-1"
}
],
"duration": "PT1H26M",
"id": "6-8e9d45c1221544f3be76394fa1a6a102"
},
"service": {
"id": "yle-areena"
},
"publisher": [
{ "id": "yle-areena" }
]
}
Again, the relevant part here is the media
Object and most notably it’s id
. Also, if you aren’t watching the
program from Finland, you should make sure region == "World"
. Only handful of videos are available for viewing
outside of Finland for licensing reasons.
Step 3: Retrieving media URL
Now, using the combination of program id and media ID, you can retrieve URL to the media. You also must provide the protocol, in our example we use HLS (HTTP Live Streaming) but you can alternatively use HDS (HTTP Dynamic Streaming).
curl -v "https://external.api.yle.fi/v1/media/playouts.json?program_id=1-820561&media_id=6-8e9d45c1221544f3be76394fa1a6a102&protocol=HLS&app_id=YOUR_APP_ID&app_key=YOUR_APP_KEY" \
| python -mjson.tool
If this produced an error, please make sure that you actually got an active program ID from Areena, as described at Step 1.
Unfortunately at the moment we’ve had to limit access to some content (most notably news content and DRM protected content). If you get a 403 error with correct app keys, please try again with different program. Also see documentation on detecting media’s availability.
Once again you get a json file containing information about the media such as width and height, but the most relevant part is the url field
WMkQT+/vPKp/IFGbv5vQfS/BzY0GEAy2SjZWNQHm4JWmzS438ffs++ntWPYeNDAUy4W/FuFA9PN2fS7BuAsuQfnJIBSv7PT2x8zxqI2mxjzQUSdCeoAblwn9Wy/weEi8LpnDyOsy+SmnfFRgeiQ98viY/bQZ5z6d06k86QuGrB2JB3M18uuiVUXWPuG/gz4s22A218tuvAEf5HMWDaY0xTIyqhk/CNXgX9e9KwsPnPisp3xomjJ7vNPlhXx/xLMK2I1Kxeq01ciolXks5SWJAsOAfRoWxWhivoUCniLsXxmcuUYhWqiKQJYgr52YGd0yyvtk85PaakVrTE/BOBhKyhKkEjYJX9Qf1UEiPFE6qBdSuBwGd4Ixdpg9m+mHS8D8/CfmMk1dPs/guHDXjAMshA==
NOTE: This URL won’t work for you, because it’s encrypted using different secret than you have. Please make the above REST call yourself when trying out the API.
Admittedly, that’s one strange looking url. The reason is that the url is encrypted (to protect illegal copying of the content) and we need to decrypt it to use it.
Step 4: Decrypting the media URL
You can use this handy tool below to decrypt the URL:
Encrypted URL: Secret:
Decrypted url
The JavaScript implementation is also available here as a reference implementation. But, for the sake of it, here’s the step-by-step instructions to decrypt the URL by yourself:
-
First, base64 decode the encrypted url
-
Then take the first 16 bytes of the decoded url as
$IV
and the rest as$MESSAGE
-
Create a cipher with
AES/CBC/PKCS7Padding
(AES/CBC/PKCS5Padding
in JVM based languages) -
Initialize the cipher in decrypt mode with your
$SECRET
and$IV
-
Decrypt the
$MESSAGE
using the cipher
Here is an example in Java:
import javax.crypto.Cipher;
import javax.crypto.spec.*;
import java.util.Base64;
import java.util.Arrays;
public class Decrypt {
public static void main(String args[]) throws Exception {
String secret = "this_is_your_secret";
String data = "this_is_the_url";
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] baseDecoded = Base64.getDecoder().decode(data);
byte[] iv = Arrays.copyOfRange(baseDecoded, 0, 16);
byte[] msg = Arrays.copyOfRange(baseDecoded, 16, baseDecoded.length);
SecretKeySpec secretKeySpec = new SecretKeySpec(secret.getBytes("UTF-8"), "AES");
IvParameterSpec ivSpec = new IvParameterSpec(iv);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivSpec);
byte[] resultBytes = cipher.doFinal(msg);
System.out.println(new String(resultBytes));
}
}
Step 5: Play the file!
Now, just copy paste the URL to QuickTime. (File -> Open Location on OS X) and hit Open to play the video.
Alternatively you can test HDS streams using Akamai test player
NOTE: If the video doesn’t work, try getting a new encrypted url and decrypt it again. The download link expires shortly after it’s created, if it isn’t consumed.
Step 6: Report your usage
Now we ask you to report your usage. Each time you or one of your users start playing a video, we’d like to know about that. There’s a simple way to do it:
curl -v "https://external.api.yle.fi/v1/tracking/streamstart?program_id=1-820561&media_id=6-8e9d45c1221544f3be76394fa1a6a102&app_id=YOUR_APP_ID&app_key=YOUR_APP_KEY"
Please call the API only the first time per each page load. If you pause, and then resume watching, you shouldn’t call the API again. But if the user refreshes the page and starts playing again, you should report a new stream start.
Step 7: What now?
Whew, now you’re finished with the tutorial. So, what now? Well, the rest is up to you.
Thanks for reading this tutorial!