Packages
Elixir library to consume the public part REST API of FranceTélévisions Video Factory.
Retired package: Security issue - privacy reason
Current section
Files
Jump to
Current section
Files
lib/ex_video_factory.ex
defmodule ExVideoFactory do
@moduledoc """
Elixir wrapper for France**Télévisions** Video Factory API.
"""
@doc """
Get the list of `videos`.
## Options
* `query`: Map of parameters to filter the query
- q: query string in title, additional_title, original_title (case insensitive)
- qid: filter with the video identifier
- page: page index
- per_page: number of items per page
- etc.
## Response example
```elixir
%{
videos: [
%{
"id": "978f7146-41e3-11e6-8153-000d3a23d482",
"created_at": "2015-09-16T10:55:12.200+02:00",
"updated_at": "2015-09-16T10:55:12.200+02:00",
"created_by": nil,
"created_via": "import-plurimedia-epg",
"title": "Amour, gloire et beauté",
"additional_title": "La vengeance de Samantha",
"category": %{
"id": "series-fictions",
"label": "séries & fictions"
},
...
"images": [%{image}, %{image}, ...],
"licensing": "svod",
"embeddable": true,
...
"platforms": %{
"ftv": %{ ... },
"bouygues": %{ ... },
"orange": %{ ... },
...
}
"groups": [
%{
"id": "ea2bed61-47e0-4116-bf8c-33c375fd9030",
"label": "Amour, gloire et beauté - Saison 13",
...
"images": [%{image}, %{image}, ...],
},
...
]
},
...
],
size: 10,
offset: 0,
total: 16238
}
```
"""
def videos(query \\ %{}) do
page =
Map.get(query, "page", 1)
|> force_integer
page_size =
Map.get(query, "per_page", 20)
|> force_integer
query =
query
|> format_query
response = ExVideoFactory.Client.get("videos", [query: query])
total = get_total_number_of_elements(response)
list = response.body
%{
videos: list,
size: length(list),
offset: (page - 1) * page_size + 1,
total: total
}
end
@doc """
Get the list of `regions`.
## Response example
```elixir
%{
regions: [
%{
"id": "saint-pierre-et-miquelon",
"label": "Saint-Pierre et Miquelon",
"code": "SPM",
"time_zone": "America/Miquelon"
},
...
],
size: 10,
total: 12
}
```
"""
def regions do
response = ExVideoFactory.Client.get("regions")
list = response.body
total = get_total_number_of_elements(response)
%{
regions: list,
size: length(list),
total: total
}
end
@doc """
Get the list of `types`.
## Response example
```elixir
%{
types: [
%{
"id": "bande-annonce",
"label": "Bande-Annonce"
},
...
],
size: 10,
total: 24
}
```
"""
def types do
response = ExVideoFactory.Client.get("types")
list = response.body
total = get_total_number_of_elements(response)
%{
types: list,
size: length(list),
total: total
}
end
@doc """
Get the list of `channels`.
## Response example
```elixir
%{
"channels": [
%{
"id": "saint-pierre-et-miquelon-1ere",
"label": "Saint-Pierre et Miquelon 1ère",
"region": %{
"id": "saint-pierre-et-miquelon",
"label": "Saint-Pierre et Miquelon"
"code": "SPM",
"time_zone": "America/Miquelon"
},
"tags": ["outremer"]
},
...
],
"size": 10,
"total": 30
}
```
"""
def channels do
response = ExVideoFactory.Client.get("channels")
list = response.body
total = get_total_number_of_elements(response)
%{
channels: list,
size: length(list),
total: total
}
end
defp get_total_number_of_elements(response) do
response.headers['X-Total-Count']
end
defp force_integer(param) when is_bitstring(param) do
param
|> String.to_integer
end
defp force_integer(param) do
param
end
@doc false
def format_query(query) do
query
|> Enum.map(fn {key, value} ->
format_field(key, value)
end
)
|> Map.new
end
defp format_field(key, value) do
format_field(key, String.split(key, "_"), value)
end
defp format_field(_, [prefix, "after"], value) do
{prefix <> "_at[gte]", format_iso8601(value)}
end
defp format_field(_, [prefix, "before"], value) do
{prefix <> "_at[lte]", format_iso8601(value)}
end
defp format_field("channels", _, value) do
{"channel.id[in]", Enum.join(value, ",")}
end
defp format_field(key, _, value) do
{key, value}
end
defp format_iso8601(date) do
char = String.at(date, 19)
case char do
" " ->
String.replace(date, ~r/\s/, "+")
nil ->
raise ArgumentError, message: "Unsupported date format: " <> date
_ ->
date
end
end
@doc """
Get the list of files on FTP server based on `Video` identifier.
## Response example
```elixir
[
"/ftp/file/path/quality_1.mp4",
"/ftp/file/path/quality_2.mp4",
"/ftp/file/path/quality_3.mp4",
"/ftp/file/path/quality_4.mp4",
"/ftp/file/path/quality_5.mp4",
]
```
"""
def get_ftp_paths_for_video_id(id) do
query = %{"external_ids.video_id": id, per_page: 1000}
ExVideoFactory.Client.get("files", [query: query]).body
|> get_files
end
@doc """
Get the list of files on FTP server based on `Video` diffusion identifier.
## Response example
```elixir
[
%{
format: "hds_akamai",
urls: []
},
%{
format: "m3u8-download",
urls: [
"/ftp/file/path/quality_1.mp4",
"/ftp/file/path/quality_2.mp4",
"/ftp/file/path/quality_3.mp4",
"/ftp/file/path/quality_4.mp4"
]
},
%{
format: "hls_v5_os",
urls: [
"/ftp/file/path/quality_1.mp4",
"/ftp/file/path/quality_2.mp4",
"/ftp/file/path/quality_3.mp4",
"/ftp/file/path/quality_4.mp4",
"/ftp/file/path/quality_5.mp4"
]
}
]
```
"""
def get_ftp_paths_for_id_diffusion(id_diffusion) do
query = [idDiffusion: id_diffusion]
ExVideoFactory.LegacyClient.get("getInfosOeuvre/v2/", [query: query]).body
|> get_legacy_files
end
@doc false
def get_files(content) do
content
|> format_files([])
end
@doc false
def get_legacy_files(content) do
content
|> Map.get("videos")
|> format_legacy_files([])
end
defp format_files([], list), do: list
defp format_files([item | items], list) do
list =
case format_file(item) do
nil -> list
filename -> List.insert_at(list, -1, filename)
end
format_files(items, list)
end
defp format_legacy_files([], list), do: list
defp format_legacy_files([item | items], list) do
list =
case item do
%{"format" => _format, "url" => nil} ->
list
%{"format" => format, "url" => url} ->
item = %{
format: format,
urls: format_url(url)
}
List.insert_at(list, -1, item)
end
format_legacy_files(items, list)
end
defp format_url("http://replayftv-vh.akamaihd.net/i/" <> url) do
list = String.split(url, ",")
[base_root, _extension] =
Enum.filter(list, fn(item) -> ! is_standard(item) end)
qualities =
Enum.filter(list, fn(item) -> is_standard(item) end)
for quality <- qualities do
"/343079/http/#{base_root}#{quality}.mp4"
end
end
defp format_url(_url) do
[]
end
defp is_standard("standard" <> _id), do: true
defp is_standard(_something), do: false
defp format_file(%{"format" => %{"id" => "video-mp4", "mime_type" => "video/mp4"}} = item) do
case Map.get(item, "storage") do
"akamai-replay-prod" ->
path = Map.get(item, "path")
filename = Map.get(item, "filename")
"/343079/http" <> path <> filename
_ -> nil
end
end
defp format_file(_item) do
nil
end
end