Skip to content

Commit f70d87a

Browse files
committed
Added stitching support
1 parent 86d4a4f commit f70d87a

7 files changed

+219
-10
lines changed

autoload.php

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"Exceptions/QencodeApiException.php",
55
"Exceptions/QencodeClientException.php",
66
"Classes/TranscodingTask.php",
7+
"Classes/StitchVideoItem.php",
78
"Classes/TranscodingTaskCollection.php",
89
"Classes/CustomTranscodingParams.php",
910
"Classes/Destination.php",

examples/start_encode2_stitch.php

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
<?php
2+
require_once __DIR__ . '/../autoload.php';
3+
4+
use Qencode\Exceptions\QencodeApiException;
5+
use Qencode\Exceptions\QencodeClientException;
6+
use Qencode\Exceptions\QencodeException;
7+
use Qencode\Classes\CustomTranscodingParams;
8+
use Qencode\Classes\Format;
9+
use Qencode\Classes\Stream;
10+
use Qencode\Classes\Destination;
11+
use Qencode\Classes\Libx264_VideoCodecParameters;
12+
use Qencode\QencodeApiClient;
13+
14+
// Replace this with your API key
15+
// API key can be found in your account on https://cloud.qencode.com under Project settings
16+
$apiKey = '5a5db6fa5b4c5';
17+
18+
$video1_url = 'https://qa.qencode.com/static/1.mp4';
19+
$video2_url = 'https://qa.qencode.com/static/bbb_sunflower_1080p_60fps_normal_339mb.mp4';
20+
21+
$q = new QencodeApiClient($apiKey);
22+
23+
try {
24+
25+
$task = $q->createTask();
26+
log_message("Created task: ".$task->getTaskToken());
27+
28+
$task->AddStitchVideoItem($video1_url);
29+
$videoItem = $task->AddStitchVideoItem($video2_url);
30+
//set start time (in seconds) in input video to begin transcoding from
31+
$videoItem->start_time = 30.0;
32+
//duration of the video fragment (in seconds) to be transcoded
33+
$videoItem->duration = 10.0;
34+
35+
$params = new CustomTranscodingParams();
36+
37+
$format = new Format();
38+
39+
$format->destination = new Destination();
40+
// Replace settings below with your destination settings
41+
$format->destination->url = "s3://s3-your-region.amazonaws.com/your-bucket/folder";
42+
$format->destination->key = "your-access-key";
43+
$format->destination->secret = "your-secret-key";
44+
$format->destination->permissions = "public-read";
45+
46+
$format->segment_duration = 4;
47+
$format->output = "advanced_hls";
48+
49+
$stream = new Stream();
50+
$stream->size = "1920x1080";
51+
$stream->audio_bitrate = 128;
52+
53+
$format->stream = [$stream];
54+
$params->format = [$format];
55+
56+
$task->startCustom($params);
57+
58+
do {
59+
sleep(5);
60+
$response = $task->getStatus();
61+
if (is_array($response) and array_key_exists('percent', $response)) {
62+
log_message("Completed: {$response['percent']}%");
63+
}
64+
} while ($response['status'] != 'completed');
65+
66+
foreach ($response['videos'] as $video) {
67+
log_message($video['user_tag'] . ': ' . $video['url']);
68+
}
69+
echo "DONE!";
70+
71+
} catch (QencodeClientException $e) {
72+
// We got some inconsistent state in client application (e.g. task_token not found when requesting status)
73+
log_message('Qencode Client Exception: ' . $e->getCode() . ' ' . $e->getMessage());
74+
} catch (QencodeApiException $e) {
75+
// API response status code was not successful
76+
log_message('Qencode API Exception: ' . $e->getCode() . ' ' . $e->getMessage());
77+
} catch (QencodeException $e) {
78+
// API call failed
79+
log_message('Qencode Exception: ' . $e->getMessage());
80+
var_export($q->getLastResponseRaw());
81+
}
82+
83+
function log_message($msg) {
84+
echo $msg."\n";
85+
}

examples/start_encode_stitch.php

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?php
2+
require_once __DIR__ . '/../autoload.php';
3+
4+
use Qencode\Exceptions\QencodeApiException;
5+
use Qencode\Exceptions\QencodeException;
6+
use Qencode\QencodeApiClient;
7+
8+
// Replace this with your API key
9+
// API key and params below, such as transcoding profile id and transfer method id
10+
// can be found in your account on https://cloud.qencode.com under Project settings
11+
$apiKey = '5a5db6fa5b4c5';
12+
$transcodingProfileId = '5a5db6fa5b8ac,5a5db6fa5c263';
13+
$transferMethodId = 'abcdefgh';
14+
15+
$video1_url = 'https://qa.qencode.com/static/1.mp4';
16+
$video2_url = 'https://qa.qencode.com/static/bbb_sunflower_1080p_60fps_normal_339mb.mp4';
17+
18+
19+
$q = new QencodeApiClient($apiKey);
20+
21+
try {
22+
23+
$task = $q->createTask();
24+
log_message("Created task: ".$task->getTaskToken());
25+
$task->AddStitchVideoItem($video1_url);
26+
$videoItem = $task->AddStitchVideoItem($video2_url);
27+
//set start time (in seconds) in input video to begin transcoding from
28+
$videoItem->start_time = 30.0;
29+
//duration of the video fragment (in seconds) to be transcoded
30+
$videoItem->duration = 10.0;
31+
32+
$task->start($transcodingProfileId, null, $transferMethodId);
33+
34+
do {
35+
sleep(5);
36+
$response = $task->getStatus();
37+
if (is_array($response) and array_key_exists('percent', $response)) {
38+
log_message("Completed: {$response['percent']}%");
39+
}
40+
} while ($response['status'] != 'completed');
41+
42+
foreach ($response['videos'] as $video) {
43+
log_message($video['user_tag'] . ': ' . $video['url']);
44+
}
45+
echo "DONE!";
46+
47+
48+
} catch (QencodeClientException $e) {
49+
// We got some inconsistent state in client application (e.g. task_token not found when requesting status)
50+
log_message('Qencode Client Exception: ' . $e->getCode() . ' ' . $e->getMessage());
51+
} catch (QencodeApiException $e) {
52+
// API response status code was not successful
53+
log_message('Qencode API Exception: ' . $e->getCode() . ' ' . $e->getMessage());
54+
} catch (QencodeException $e) {
55+
// API call failed
56+
log_message('Qencode Exception: ' . $e->getMessage());
57+
var_export($q->getLastResponseRaw());
58+
}
59+
60+
function log_message($msg) {
61+
echo $msg."\n";
62+
}

src/Classes/CustomTranscodingParams.php

+4
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,9 @@ class CustomTranscodingParams {
1515
*/
1616
public $format;
1717

18+
/**
19+
* An endpoint address to accept a webhook notification on job events
20+
* @var string
21+
*/
1822
public $callback_url;
1923
}

src/Classes/StitchVideoItem.php

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
namespace Qencode\Classes;
4+
5+
6+
class StitchVideoItem
7+
{
8+
/**
9+
* Source video URI. Can be http(s) url or tus uri
10+
* @var string
11+
*/
12+
public $url;
13+
14+
/**
15+
* Video clip start time
16+
*/
17+
public $start_time;
18+
19+
/**
20+
* Video clip duration
21+
*/
22+
public $duration;
23+
24+
}

src/Classes/TranscodingTask.php

+31-5
Original file line numberDiff line numberDiff line change
@@ -57,20 +57,43 @@ public function __construct($api, $task_token) {
5757
$this->subtitles = null;
5858
}
5959

60+
private $stitchVideoItems;
61+
/**
62+
* Adds a video for stitching
63+
* @param string $url Source video URI. Can be http(s) url or tus uri
64+
* @return StitchVideoItem
65+
*/
66+
public function AddStitchVideoItem($url) {
67+
$item = new StitchVideoItem();
68+
if ($this->stitchVideoItems == undefined) {
69+
$this->stitchVideoItems = [];
70+
}
71+
$item->url = $url;
72+
$this->stitchVideoItems[] = $item;
73+
return $item;
74+
}
75+
6076
/**
6177
* Starts transcoding job using specified transcoding profile or list of profiles
6278
* @param string|array $transcodingProfiles One or several transcoding profile identifiers. Can be comma-separated string or an array
63-
* @param string $uri a link to input video or TUS uri
79+
* @param string $uri a link to input video or TUS uri (ignored in case of stitching)
6480
* @param string $transferMethod Transfer method identifier
6581
* @param string $payload Any string data of 1000 characters max length. E.g. you could pass id of your site user uploading the video or any json object.
6682
* @return array start_encode API method response
6783
*/
68-
public function start($transcodingProfiles, $uri, $transferMethod = null, $payload = null) {
84+
public function start($transcodingProfiles, $uri = null, $transferMethod = null, $payload = null) {
6985
$params = array(
7086
'task_token' => $this->taskToken,
71-
'uri' => $uri,
7287
'profiles' => is_array($transcodingProfiles) ? implode(',', $transcodingProfiles) : $transcodingProfiles
7388
);
89+
//echo 'stitchVideoItems: '.print_r($this->stitchVideoItems, true);
90+
$arrays = null;
91+
if (is_array($this->stitchVideoItems)) {
92+
$arrays = array('stitch' => $this->stitchVideoItems);
93+
}
94+
else {
95+
$params['uri'] = $uri;
96+
}
7497
if ($transferMethod) {
7598
$params['transfer_method'] = $transferMethod;
7699
}
@@ -89,7 +112,7 @@ public function start($transcodingProfiles, $uri, $transferMethod = null, $paylo
89112
if ($this->subtitles) {
90113
$params['subtitles'] = json_encode($this->subtitles);
91114
}
92-
$response = $this->api->post('start_encode', $params);
115+
$response = $this->api->post('start_encode', $params, $arrays);
93116
$this->statusUrl = $response['status_url'];
94117
return $response;
95118
}
@@ -101,10 +124,13 @@ public function start($transcodingProfiles, $uri, $transferMethod = null, $paylo
101124
* @return array start_encode API method response
102125
*/
103126
public function startCustom($task_params, $payload = null) {
127+
if (is_array($this->stitchVideoItems)) {
128+
$task_params->stitch = $this->stitchVideoItems;
129+
}
104130
$query = array ('query' => $task_params);
105131
$query_json = json_encode($query);
106132
$query_json = preg_replace('/,\s*"[^"]+":null|"[^"]+":null,?/', '', $query_json);
107-
echo $query_json."<br><br>";
133+
//echo $query_json."\n\n";
108134
$params = array(
109135
'task_token' => $this->taskToken,
110136
'query' => $query_json

src/QencodeApiClient.php

+12-5
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,9 @@ public function getItemCount()
100100
* @throws \Qencode\Exceptions\QencodeApiException if the API call status code is not in the 2xx range
101101
* @throws QencodeException if the API call has failed or the response is invalid
102102
*/
103-
public function post($path, $params = [], $url = null)
103+
public function post($path, $params = [], $arrays = null)
104104
{
105-
return $this->request('POST', $path, $params);
105+
return $this->request('POST', $path, $params, $arrays);
106106
}
107107

108108
/**
@@ -133,7 +133,7 @@ public function getLastResponse()
133133
* @throws \Qencode\Exceptions\QencodeApiException
134134
* @throws \Qencode\Exceptions\QencodeException
135135
*/
136-
private function request($method, $path, array $params = [])
136+
private function request($method, $path, array $params = [], $arrays = null)
137137
{
138138
$this->lastResponseRaw = null;
139139
$this->lastResponse = null;
@@ -144,13 +144,20 @@ private function request($method, $path, array $params = [])
144144
else {
145145
$url = $this->url . '/' . $this->version . '/' . trim($path, '/');
146146
}
147-
echo "URL: ".$url."\n";
147+
//echo "URL: ".$url."\n";
148148
if (!empty($params) & is_array($params)) {
149149
$params = http_build_query($params);
150150
}
151+
if (is_array($arrays)) {
152+
foreach ($arrays as $key => $value) {
153+
$encoded_value = json_encode($value);
154+
$encoded_value = preg_replace('/,\s*"[^"]+":null|"[^"]+":null,?/', '', $encoded_value);
155+
$params .= '&'.$key.'='.$encoded_value;
156+
}
157+
}
151158
#echo $url;
152159
#echo "\n";
153-
#echo $params."\n\n";
160+
//echo $params."\n\n";
154161
$curl = curl_init($url);
155162

156163
curl_setopt($curl, CURLOPT_USERPWD, $this->key);

0 commit comments

Comments
 (0)