Skip to content

Commit

Permalink
add video details
Browse files Browse the repository at this point in the history
  • Loading branch information
dimmetrius committed Nov 17, 2019
1 parent c39111e commit d49bd8e
Show file tree
Hide file tree
Showing 10 changed files with 271 additions and 23 deletions.
6 changes: 6 additions & 0 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ const bodyParser = require('body-parser');

const index = require('./routes/index');
const upload = require('./routes/upload');
const video = require('./routes/video');
const transcriptions = require('./routes/transcriptions');
const airesult = require('./routes/airesult');

const app = express();

Expand All @@ -23,6 +26,9 @@ app.use(express.static(path.join(__dirname, 'public')));

app.use('/', index);
app.use('/upload', upload);
app.use('/video', video);
app.use('/transcription', transcriptions);
app.use('/airesult', airesult);

// catch 404 and forward to error handler
app.use((req, res, next) => {
Expand Down
9 changes: 8 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ const _log = value => {

const DELETE_ASSETS = true;

const processing = {};

// endpoint config
// make sure your URL values end with '/'

Expand Down Expand Up @@ -207,7 +209,7 @@ const processVideBlob = async (id, nm) => {
);

// Choose between the Audio and Video analyzer transforms
let transformName = selectTransform(AUDIO_ANALIZE);
let transformName = selectTransform(/*AUDIO_ANALIZE*/);

_log('submitting job...');
let job = await submitJob(
Expand Down Expand Up @@ -462,8 +464,13 @@ function videoAnalyzerPreset() {
};
}

const getStatus = id => {
return processing[id];
};

const serv = {
processVideBlob: processVideBlob,
status: getStatus,
};

module.exports = serv;
12 changes: 8 additions & 4 deletions public/stylesheets/style.css
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
body {
padding: 50px;
font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
font: 14px 'Lucida Grande', Helvetica, Arial, sans-serif;
}

a {
color: #00B7FF;
color: #00b7ff;
}

.upload-container {
border: solid 1px #ccc;
padding: 10px;
max-width: fit-content;
margin-bottom: 10px
}
margin-bottom: 10px;
}

.face_img {
margin: 5px;
}
23 changes: 23 additions & 0 deletions routes/airesult.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
if (process.env.NODE_ENV !== 'production') {
require('dotenv').load();
}

const express = require('express'),
router = express.Router(),
azureStorage = require('azure-storage'),
blobService = azureStorage.createBlobService(),
config = require('../config');

router.get('/:videoId/:fileId', (req, res, next) => {
const videoId = req.param('videoId');
const fileId = req.param('fileId');

blobService.getBlobToStream(
'transcriptions',
videoId + '/' + fileId,
res,
() => {}
);
});

module.exports = router;
6 changes: 5 additions & 1 deletion routes/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ router.get('/', (req, res, next) => {
};

if (data.entries.length) {
viewData.thumbnails = data.entries;
viewData.thumbnails = data.entries.map(entry => {
const split = entry.name.split('/');
const id = split[0];
return { ...entry, id };
});
}
}

Expand Down
56 changes: 56 additions & 0 deletions routes/transcriptions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
if (process.env.NODE_ENV !== 'production') {
require('dotenv').load();
}

const express = require('express'),
router = express.Router(),
azureStorage = require('azure-storage'),
blobService = azureStorage.createBlobService(),
config = require('../config');

router.get('/:videoId', (req, res, next) => {
const videoId = req.param('videoId');

blobService.getBlobToStream(
'transcriptions',
videoId + '/transcript.vtt',
res,
() => {}
);
/*
blobService.listBlobsSegmented('videos', null, (err, data) => {
let viewData;
if (err) {
viewData = {
title: 'Error',
viewName: 'error',
message: 'There was an error contacting the blob storage container.',
error: err,
};
res.status(500);
} else {
viewData = {
message: 'MSG',
title: 'Home',
viewName: 'video',
accountName: config.getStorageAccountName(),
containerName: 'videos',
};
if (data.entries.length) {
viewData.videos = data.entries
.filter(entry => entry.name.indexOf(videoId + '/') == 0)
.map(data => {
return { ...data, id: videoId };
});
}
}
res.render(viewData.viewName, viewData);
});
*/
});

module.exports = router;
47 changes: 47 additions & 0 deletions routes/video.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
if (process.env.NODE_ENV !== 'production') {
require('dotenv').load();
}

const express = require('express'),
router = express.Router(),
azureStorage = require('azure-storage'),
blobService = azureStorage.createBlobService(),
config = require('../config');

router.get('/:videoId', (req, res, next) => {
const videoId = req.param('videoId');
blobService.listBlobsSegmented('videos', null, (err, data) => {
let viewData;

if (err) {
viewData = {
title: 'Error',
viewName: 'error',
message: 'There was an error contacting the blob storage container.',
error: err,
};

res.status(500);
} else {
viewData = {
message: 'MSG',
title: 'Home',
viewName: 'video',
accountName: config.getStorageAccountName(),
containerName: 'videos',
};

if (data.entries.length) {
viewData.videos = data.entries
.filter(entry => entry.name.indexOf(videoId + '/') == 0)
.map(data => {
return { ...data, id: videoId };
});
}
}

res.render(viewData.viewName, viewData);
});
});

module.exports = router;
3 changes: 1 addition & 2 deletions views/error.hbs
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
<h1>{{message}}</h1>
<h2>{{error.status}}</h2>
<pre>{{error.stack}}</pre>
<h2>{{error.status}}</h2>
32 changes: 17 additions & 15 deletions views/index.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,27 @@

<h2>Processed Videos</h2>
{{#each this.thumbnails}}
<video width="300" height="170" src="https://{{../accountName}}.blob.core.windows.net/{{../containerName}}/{{name}}"></video>
<a href="/video/{{id}}"><video width="300" height="170"
src="https://{{../accountName}}.blob.core.windows.net/{{../containerName}}/{{name}}">
</video></a>
{{/each}}

<script>
document.addEventListener('DOMContentLoaded', () => {
<script>
document.addEventListener('DOMContentLoaded', () => {
const message = document.getElementById('message');
const picker = document.getElementById('file-picker');
const message = document.getElementById('message');
const picker = document.getElementById('file-picker');
document.getElementById('upload-form').addEventListener('submit', (e) => {
document.getElementById('upload-form').addEventListener('submit', (e) => {
message.innerText = '';
if (!picker.files.length) {
message.innerText = 'Please select an video to upload.';
e.preventDefault();
return false;
}
});
message.innerText = '';
if (!picker.files.length) {
message.innerText = 'Please select an video to upload.';
e.preventDefault();
return false;
}
});
</script>
});
</script>
100 changes: 100 additions & 0 deletions views/video.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
<h1>Video Analisys</h1>

{{#each this.videos}}
<video id='video' width="600" controls
src="https://{{../accountName}}.blob.core.windows.net/{{../containerName}}/{{name}}">
<track default src="/airesult/{{id}}/transcript.vtt">
</video>

<br>
<h1>Insights</h1>
<div id="transcription"></div>
<div id='faces'></div>
<div id='labels'></div>
<div id='sentiments'></div>
<script>
function setVideoTime(num) {
const videoEl = document.getElementById("video");
videoEl.currentTime = num;
videoEl.scrollIntoView();
}
function jumpTo(str) {
const timeParts = str.split(':');
if (timeParts.length === 3) {
const sec = parseFloat(timeParts[0]) * 60 * 60 + parseFloat(timeParts[1]) * 60 + parseFloat(timeParts[2])
setVideoTime(sec);
}
}
document.addEventListener('DOMContentLoaded', async () => {
const insightsFetch = await fetch("/airesult/{{id}}/insights.json");
const insights = await insightsFetch.json();
const transcript = insights.transcript || [];
const transcription = transcript.map(el => el.text).join('');
if (transcription) {
const el = document.getElementById('transcription');
var oh = document.createElement("h2");
oh.innerText = 'Transcription:';
el.appendChild(oh);
var div = document.createElement("div");
div.innerText = transcription;
el.append(div);
}
const faces = insights.faces || [];
if (faces.length) {
const el = document.getElementById('faces');
var oh = document.createElement("h2");
oh.innerText = 'Faces:';
el.appendChild(oh);
faces.forEach(f => {
var oImg = document.createElement("img");
oImg.setAttribute('src', "/airesult/{{id}}/" + "FaceThumbnail_" + f.thumbnailId + ".jpg");
oImg.setAttribute('width', '150px');
oImg.setAttribute('class', 'face_img');
el.appendChild(oImg);
})
}
const labels = insights.labels || [];
if (labels.length) {
const el = document.getElementById('labels');
var oh = document.createElement("h2");
oh.innerText = 'Labels:';
el.appendChild(oh);
labels.forEach(f => {
var oLabel = document.createElement("div");
const start = ((f.instances || [])[0] || {})['start']
oLabel.innerText = f.name;
oLabel.onclick = () => { jumpTo(start) }
el.appendChild(oLabel);
})
}
const sentiments = insights.sentiments || [];
if (sentiments.length) {
const el = document.getElementById('sentiments');
var oh = document.createElement("h2");
oh.innerText = 'Sentiments:';
el.appendChild(oh);
sentiments.forEach(f => {
var oLabel = document.createElement("div");
oLabel.innerText = f.sentimentType;
el.appendChild(oLabel);
})
}
});
</script>
{{/each}}

0 comments on commit d49bd8e

Please sign in to comment.