Skip to content

Instantly share code, notes, and snippets.

@ayozehd
Created October 18, 2019 17:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ayozehd/f8dab66db80c0122475fed80115a1a02 to your computer and use it in GitHub Desktop.
Save ayozehd/f8dab66db80c0122475fed80115a1a02 to your computer and use it in GitHub Desktop.
Video previews Transloadit Sample (Symfony, Twig, Javascript)
<?php
namespace AppBundle\Controller;
use App\Entity;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\JsonResponse;
use transloadit\Transloadit;
use Exception;
class AssemblyController extends Controller
{
protected $em;
protected $logger;
/**
* @Route("/assembly/answer", name="assemblyAnswerVideo", methods={"POST"})
*/
public function assemblyAnswerVideoAction(Request $request)
{
$this->initialize();
$answer_id = $request->query->get('answer_id');
$answer = $this->em
->getRepository('App:Answer')
->find($answer_id);
if($answer instanceof Entity\Answer) {
$response = Transloadit::response();
if (!$response->error()) {
$results = $response->data['results'];
foreach($results as $step => $result) {
switch($step) {
case 'watermarked':
$answer->setVideoMp4($result[0]['ssl_url']);
break;
case 'webm_encode':
$answer->setVideoWebm($result[0]['ssl_url']);
break;
case 'ogv_encode':
$answer->setVideoOgv($result[0]['ssl_url']);
break;
case 'thumbailed':
$answer->setVideoThumbnail($result[0]['ssl_url']);
break;
default:
}
}
$answer->setVideoProcess(false);
$this->em->flush();
$question = $answer->getParent();
$user = $question->getUser();
$locale = $user->getLocale();
$this->get('app.mailer')
->new(
$user->getEmail(),
$this->get('translator')->trans('question.answered', [], 'messages', $locale),
'email/answered-question.html.twig',
[
'url' => $this->generateUrl('answer', array('username' => $user->getUsername(), 'hash' => $enquiry->getHash()), true),
'locale' => $locale
]
);
$this->logger->info('[Assembly Notification] We received an assembly notification succesfully', [
'answer_id' => $answer_id
]);
return $this->response();
} else {
$this->logger->error('[Assembly Notification] Transloadit returned an error response', [
'answer_id' => $answer_id,
'error_msg' => $response
]);
}
} else {
$this->logger->critical('[Assembly Notification] We cannot find the answer ID for a Transload Assembly Notification. Check database integrity.', [
'answer_id' => $answer_id
]);
}
return $this->response(false);
}
// ...
protected function response($success = true)
{
$response = new JsonResponse(
array(
'success' => $success,
)
);
if(!$success) {
$response->setStatusCode(400);
}
return $response;
}
protected function initialize() {
$this->em = $this->getDoctrine()->getManager();
$this->logger = $this->get('monolog.logger.transload');
}
}
{% extends "base.html.twig" %}
{% block content %}
<form method="post" action="{{ path('messageReplySubmit', {id: message.id}) }}">
...
</form>
{% endblock %}
{% block javascript %}
{{ parent() }}
<script src="{{ asset('/js/uppy.min.js') }}"></script>
<script type="text/javascript">
const supportedBrowserVideoFormats = [
'video/mp4',
'video/webm',
'video/ogg'
];
var uppy = buildUppyWidget();
uppy.on('upload', (data) => {
disableFormSubmission();
});
uppy.on('transloadit:complete', (assembly) => {
if(assembly.ok != 'error') {
var upload, preview, poster = null;
for(var i in assembly.uploads) {
upload = assembly.uploads[i].ssl_url;
}
if('mp4_encode' in assembly.results) {
for(var i in assembly.results.mp4_encode) {
preview = assembly.results.mp4_encode[i].ssl_url;
}
}
if('thumbailed' in assembly.results) {
for(var i in assembly.results.thumbailed) {
poster = assembly.results.thumbailed[i].ssl_url || assembly.results.thumbailed[i].url;
}
}
videoThumbnail(upload, preview, poster);
$('#removeFile').on('click touch', function(e) {
e.preventDefault();
restoreVideoUpload();
});
}
disableFormSubmission(true);
});
function buildUppyWidget()
{
return Uppy.Core({
debug: false,
autoProceed: true,
no_cors: true,
allowMultipleUploads: false,
restrictions: {
maxFileSize: 1024 * 1024 * 500, // Max 500MB
maxNumberOfFiles: 1,
minNumberOfFiles: 1,
allowedFileTypes: ['video/*'],
}
})
.use(Uppy.Transloadit, {
params: {
auth: {
// To avoid tampering use signatures:
// https://transloadit.com/docs/api/#authentication
key: '{{ transload_key }}'
},
template_id: '{{ transload_assembly_upload_temp }}'
},
waitForEncoding: true
})
.use(Uppy.FileInput, {
target: '#video-upload',
pretty: true
})
.use(Uppy.StatusBar, {
target: '#video-status',
hideAfterFinish: false,
hideCancelButton: true
})
.use(Uppy.Informer, {
target: 'body',
replaceTargetContent: false
});
}
function videoThumbnail(original, preview, poster) {
var div = $('.reply-thumbnail-video');
var thumbnail = `
<div class="thumbnail">
`+ addVideoData(original) + `
<video controls="1" ` + (poster ? 'poster="' + poster + '"' : null) + `>
<source src="${preview}" type="video/mp4"></video>
</div>
` + videoRemoveButton();
div.append(thumbnail);
}
function addVideoData(url) {
return `
<input type="hidden" name="video_url" value="${url}">
`;
}
function restoreVideoUpload() {
var div = $('.reply-thumbnail-video');
div.empty();
uppy.reset();
disableFormSubmission(true);
}
function videoRemoveButton() {
return `<button class="btn btn-danger btn-block" id="removeFile">Remove</button>`;
}
function disableFormSubmission(status)
{
if(!status) {
status = false;
}
$('form button[type="submit"]').prop('disabled', !status);
}
</script>
{% endblock %}
{% block stylesheets %}
{{ parent() }}
<link href="{{ asset('/css/uppy.min.css') }}" rel="stylesheet">
<link href="{{ asset('/css/custom-uppy.min.css') }}" rel="stylesheet">
{% endblock %}
<?php
namespace App\Controller;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use App\Entity;
use transloadit\Transloadit;
class ReplyController extends BaseController
{
/**
* @Route("/message/reply/{id}", name="messageReply", requirements={"id"="\d+"})
*/
public function messageReplyAction(Request $request, $id)
{
$this->initialize($request);
$user = $this->getUser();
$msg = $this->getDoctrine()
->getRepository('App:Message')
->find($id);
if(!$msg){
$this->addFlash('error', $this->get('translator')->trans('error.message.missing'));
return $this->redirectToRoute('messages');
}
return $this->render('reply.html.twig', [
'user' => $user,
'message' => $msg
]);
}
/**
* @Route("/message/reply/{id}/submit", name="messageReplySubmit", requirements={"id"="\d+"})
*/
public function messageReplySubmitAction(Request $request, $id)
{
$user = $this->getUser();
$msg = $this->getDoctrine()
->getRepository('App:Message')
->find($id);
if(!$msg){
// TODO not found exception
$this->addFlash('error', $this->get('translator')->trans('error.message.missing'));
return $this->redirectToRoute('messages');
}
if ($request->isMethod('POST')) {
$videoUrl = $request->request->get('video_url');
if(!$videoUrl || $videoUrl == '') {
$this->addFlash('error', $this->get('translator')->trans('error.message.answer_empty'));
return $this->redirectToRoute('messages');
}
$answer = new Entity\Answer();
$answer->setParent($msg);
$answer->setUser($user);
$answer->setCreatedAt(new \DateTime());
if($videoUrl) {
$answer->setVideoProcess(true);
}
$this->getDoctrine()
->getRepository('App:Answer')
->insert($answer);
// REQUEST TRANSCODE VIDEO ASYNC
if($videoUrl) {
/** @var $logger LoggerInterface */
$logger = $this->get('monolog.logger.transload');
$transloadit = new Transloadit(array(
'key' => $this->container->getParameter('transload_key'),
'secret' => $this->container->getParameter('transload_secret'),
));
$router = $this->get('router');
// Transload Assembly Notifications host on dev environment via ngrock https://ngrok.com
if($this->get('kernel')->isDebug()) {
$context = $router->getContext();
$context->setHost($this->container->getParameter('transload_assembly_host'));
$context->setScheme('http');
}
$notifyUrl = $router->generate('assemblyTopicAnswerVideo', [
'answer_id' => $answer->getId()
], true);
try {
$response = $transloadit->createAssembly(array(
'params' => array(
"notify_url" => $notifyUrl,
'template_id' => $this->container->getParameter('transload_assembly_message'),
'steps' => array(
'imported' => array(
'url' => $videoUrl
)
)
)
));
} catch(Exception $e) {
$logger->error('[Assembly Request] Something was wrong sending assembly request to Transloadit', [
'template' => $this->container->getParameter('transload_assembly_thread'),
'answer_id' => $answer->getId(),
'video_url' => $videoUrl,
'notification_url' => $notifyUrl,
'error_msg' => $e->getMessage()
]);
}
$logger->info('[Assembly Request] Video processing request to Transloadit', [
'template' => $this->container->getParameter('transload_assembly_thread'),
'answer_id' => $answer->getId(),
'video_url' => $videoUrl,
'notification_url' => $notifyUrl
]);
}
$this->addFlash('success', $this->get('translator')->trans('message.replied'));
}
return $this->redirectToRoute('messages');
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment