Professional Documents
Culture Documents
Cybersecurity in The IoT Era: Challenges and Solutions
Cybersecurity in The IoT Era: Challenges and Solutions
Керівник ___________________________
(прізвище та ініціали)
___________________________
(науковий ступінь, звання)
Київ - 2021
1
Анотація
Summary
The degree project: «Software module for processing video files and
freezing of production files» has completed by Smyrnov Oleksandr specialty 122 -
«Computer Sciences».
In the final qualifying work, the analysis of modern systems on video
coding and video editing is carried out, the software which corresponds to the set
indicators which carries out video processing of video material in the set conditions
of use is developed.
ЗМІСТ
ВСТУП..........................................................................................................................3
1. АНАЛІТИЧНИЙ ОГЛЯД.......................................................................................5
1.1. Історія відеоредагування..................................................................................5
1.2. Робота з відеоматеріалами................................................................................6
1.3 Захоплення цифрового зображення..................................................................6
1.4. Частота кадрів....................................................................................................7
1.5. Програми відтворення відео.............................................................................8
1.6. Програми обробки відео...................................................................................9
1.7. Відео кодинг......................................................................................................9
1.8. Інтеркодування................................................................................................12
1.9. Принцип кодування.........................................................................................17
1.10. Постановка задачі..........................................................................................18
2. ПОСТАНОВКА ЗАДАЧІ......................................................................................20
2.1. Завдання системи............................................................................................20
2.2. Сценарії застосування.....................................................................................22
2.2.1. Відео програвач.........................................................................................22
2.2.2 Перегляд властивостей відеоматеріалу....................................................23
2.2.3. Відео редактор...........................................................................................24
2.2.4. Відео форматування..................................................................................24
2.2.5. Веб застосунок...........................................................................................25
2.3. Методи роботи лінійності застосунку...........................................................25
2.3.1. Метод лінійного монтажу відео...............................................................25
2.3.2. Метод нелінійного монтажу відео...........................................................27
2.4 Структура роботи функцій з файлами...........................................................28
3. РЕАЛІЗАЦІЯ ТА ТЕСТУВАННЯ........................................................................33
3.1 Структура програмного застосунку...............................................................33
3.2 Графічний інтерфейс........................................................................................39
ВИСНОВОК...............................................................................................................50
ВИКОРИСТАНІ ДЖЕРЕЛА.....................................................................................51
ДОДАТКИ..................................................................................................................53
4
ВСТУП
Обробка відео – це, напевно, один із найбільш вимогливих завдань з тих,
які узагалі можна виконувати на персональному комп'ютері. Процес об’єднання
відеокліпів, зображень та звуків для створення відеоматеріалу y наш час це
робиться на комп’ютері з фантастичними програмами для редагування відео,
які називаються нелінійними редакторами або NLE. Це означає, що з цим
встановленим середовищем можена переглядати, вирізати та упорядковувати
цифрове відео у будь-якому порядку без необхідності дивитися весь
відеоматеріал.
Монтування відео є актуальним та використовується в багатьох сферах
життя. Насправді багато для відеомонтажу перенесено з давніх часів розрізання
фільмів. Наприклад, файлові системи організації в цифровому редакторі
називаються контейнерами, оскільки каністри для фільмів колись зберігалися в
контейнерах під час процесу редагування. Відеоредактор зазвичай передбачає
створення проєкту для роботи з відео. Проєкт, у даному випадку, це сукупність
всіх налаштувань і змін, які записуються в окремому файлі проєкту. У проєкті
зберігаються дані про всі зміни кліпів, розміщених на відео- і звукових
доріжках, застосованих ефектах і фільтрах, а також список усіх медіафайлів, які
були використані при монтажі. Файл проєкту можна відкрити для подальшого
монтажу, при цьому всі раніше використовувані медіафайли повинні бути
доступні за допомогою посилань, які були збережені в проєкті.
Мета і завдання роботи є створення прототипу програмного забеспечення
для його подальшого використання online без необхідності установлення
програмного забеспечення. Щоб додаток дозволяв абсолютно любому
користувачу відредагувати відеоматеріал без додаткових знань та інших
ускладнювальних процессів. Результатом розробки дипломнох роботи маємо
отримати прототип веб застосунку з відеоредагування та застосування базисних
відео ефеків.
5
1. АНАЛІТИЧНИЙ ОГЛЯД
M N
1
MSE ( x , y )= ∑ ∑ ¿¿¿
MN i=1 j=1
14
2. ПОСТАНОВКА ЗАДАЧІ
Функції експорту:
1. Формування інструкцій щодо обробки файлу.
2. Створення копії вивантажуємого файлу.
3. Застосування інструкцій щодо обробки файлу.
4. Створення нового файлу з сформованого відеоматеріалу .
5. Отримання згрупованої інформації.
6. Збереження відповіді.
30
7. Відображення відеоматеріалу.
3. РЕАЛІЗАЦІЯ ТА ТЕСТУВАННЯ
необхідно змінити розмір вікна таким чином щоб можна було паралельно
бачити робочий стіл персонального комп’ютера або відкриту директорію де
знаходиться бажаний файл та перемістити вікно програми щоби бачити
відеофайл та вікно застосунку, після чого перенести відео на вікно інтерфейсу.
Для вибору проміжутку треба задати дві точки між якими знаходиться
бажаний відеоматеріал, це можна зробити натиснувши Set start point на його
початку
ВИСНОВОК
В ході виконання випускної кваліфікаційної роботи, було спроектовано та
розроблено настільний застосунок для персонального комп’ютеру. Наприкінці
розробки отримано веб-адаптивний застосунок для монтування відео.
Застосунок має поле для відтворення та попереднього перегляду відео файлів, з
можливістю паралельно відредаговувати відеоматеріали за допомогою
інтерактивної доріжки на інтерфейсі користувача. Мається можливість
завантаження та перегляду одразу ж декількой медіафайлів у різних форматах
для створення відеоматеріалу у прогрманому продукті. На виході отримуємо
відредаговане відео у форматі .mp4.
В першому розділі нами було досліджено поняття систем
відеоредагування та розглянуто загальне становище даної теми. З першого
розділу визначається принципи кодування та форматування відео у сучасних
форматах.
У другому розділі нами було описано складові елементи системи та її
завдання, сценарії застосуванная застосунку для рядового користувача. Описані
методи лінійності відеоредактору в застосунку, скадені функції роботи з
файлами всередені розробленої системи.
В третьому розділі описуються програмна складова по функціям та
файлам програми з описом використаних бібліотек для розширення
функціоналу. Описується інтерфейс програмного застосунку та наводиться
приклад його застосування.
51
ВИКОРИСТАНІ ДЖЕРЕЛА
1. Боссен, Ф., Бросс, Б., член, С., Карстен, С. та Флін, Д. (2013).
HEVC Аналіз складності та впровадження. Схеми та системи для відеотехніки,
IEEE Transactions, 22(12):1685–1696.
2. Чунг, N.-m., Фан, X., Au, O. C., і Кунг, M.-c. (2010).
Відеокодуванняна багатоядерних графічних процесорах. Журнал обробки
сигналів, IEEE, (March):79–89.
3. Chi, C. C., Alvarez-mesa, M., Juurlink, B., Member, S., Clare, G., та
Ширіл, T. (2012). Паралельна масштабованість та ефективність підходів до
паралелізації HEVC. Схеми та системи для відеотехніки, IEEE Transactions,
22(12):1827–1838.
4. Cisco Systems, I. (2016). Індекс візуальних мереж Cisco - прогноз та
методологія.
5. Грінгал, П. (2012). big.LITTLE Обробка за допомогою ARM Cortex-
A15 і Cortex-A7. ARM, (вересень 2011 р.): 1–8. Він, Ю., Кунстнер, М.,
Гудумасу, С., Рю, Є. С., Є, Ю. та Сіу, X. (2013). Потужність. Трансляція HEVC
для мобільних пристроїв. У візуальних комунікаціях та обробці зображень
(VCIP), 2013, pages 1–5.
6. Holmbacka, S., Nogues, E., Pelcat, M., Lafond, S., and Lilius, J. (2014).
Енергоефективність та управління продуктивністю паралельних додатків
потоку даних. У „Дизайн та архітектура для обробки сигналів та зображень”
(DASIP), конференція 2014 р., Сторінки 1–8. 73 Бібліографія Джефф, B. (2012).
Досягнення технології big.LITTLE для енергозбереження та енергозбереження.
ARM, (вересень): 1–11.
7. Лі, В. Ю. (2012). Енергоефективне планування періодичних
завдань у режимі реального часу на легко завантажених багатоядерних
процесорах. Транзакції IEEE щодо паралельних та розподілених систем, 23 (3):
530–537.
8. Лі, В. Ю., Ко, Ю. В., Лі, Х. та Кім, Х. (2009). Енергоефективне
52
ДОДАТКИ
Додаток А. Функція Video.js
class Video {
constructor({
PlayerVideo,
ContainVid,
thumbcontain,
searchprogress,
lookThumb,
Timestam,
Play,
FPSelement,
DurationOf,
ControllingFrags,
BoostSpeed,
VolumePref,
BoostIn,
VolIn
}) {
fragments = [];
PlayerVideo = PlayerVideo;
ContainVid = ContainVid;
thumbcontain = thumbcontain;
searchprogress = searchprogress;
lookThumb = lookThumb;
Timestam = Timestam;
Play = Play;
FPSelement = FPSelement;
DurationOf = DurationOf;
ControllingFrags = ControllingFrags;
54
BoostSpeed = BoostSpeed;
Volumepref = Volumepref;
BoostIn = BoostIn;
VolIn = VolIn;
createContextMenu();
}
createContextMenu() {
require('electron-context-menu')({
prepend: (params, browserWindow) => [{
label: "Set start point",
click: () => {
console.log("Setting start point", activeFragment.currentPoint,
activeFragment.duration);
new SetStartPoint(activeFragment,
activeFragment.currentPoint).execute();
}
}, {
label: "Set end point",
click: () => {
new SetEndPoint(activeFragment,
activeFragment.currentPoint).execute();
55
}
}, {
label: "Split video",
click: () => {
new SplitVideo(this, activeFragment,
activeFragment.currentPoint).execute();
}
}],
shouldShowMenu: (e, params) => {
let value = shouldShowContextMenu;
shouldShowContextMenu = false;
return value;
},
showInspectElement: false
});
}
fragment.thumbnailElement.addEventListener('mouseup', () => {
56
if (!seeking) {
if (activeFragment && fragment !== activeFragment) {
activeFragment.currentTime = 0;
activeFragment = fragment;
pause();
updateTime();
fragment.addEventListener('loadedData', () => {
updateTime();
});
fragment.pause();
}
}
});
fragment.addEventListener('loadedMetadata', () => {
if (++loaded === toLoad) {
if (!activeFragment) {
currentTime = 0;
}
}
updateTime();
});
fragments.push(fragment);
}
activeFragment = fragment;
showPlayer();
}
get playerIsVisible() {
return PlayerVideo.style.display !== "none" && PlayerVideo.style.display !==
"";
}
showPlayer() {
if (!playerIsVisible) {
PlayerVideo.style.display = "block";
ControllingFrags.style.display = "block";
}
}
hidePlayer() {
if (playerIsVisible) {
PlayerVideo.style.display = "none";
ControllingFrags.style.display = "none";
}
}
removeFragment(fragment) {
fragment.pause();
58
if (fragment.element.parentNode)
fragment.element.parentNode.removeChild(fragment.element);
if (fragment.thumbnailElement.parentNode)
fragment.thumbnailElement.parentNode.removeChild(fragment.thumbnailEle
ment);
if (fragments.length === 0) {
hidePlayer();
video.activeFragment = undefined;
} else {
updateTime();
}
}
}
}
moveFragment(fragment, index) {
removeFragment(fragment);
Video.insertNodeAt(thumbcontain, fragment.thumbnailElement, index);
Video.insertNodeAt(ContainVid, fragment.element, index);
fragments.splice(index, 0, fragment);
// updateTime();
}
newFragment.startPoint = timePercent;
fragment.endPoint = timePercent;
// activeFragment = newFragment;
newFragment.addEventListener("loadedData", () => {
currentTime = time;
60
updateTime();
});
return newFragment;
}
onMouseMove(e) {
if (seeking && hoveringFragment) {
let offset = hoveringFragment.thumbnailElement.getBoundingClientRect();
let x = e.pageX - offset.left;
let width = hoveringFragment.thumbnailElement.offsetWidth;
x = x < 0 ? 0 : x;
x = x > width ? width : x;
let startTime = 0;
for (let fragment of fragments) {
if (fragment === hoveringFragment) {
break;
}
startTime += fragment.duration;
}
currentTime = startTime + hoveringFragment.duration * x / width;
}
}
set currentTime(value) {
if (value >= 0 && value <= duration) {
let prevFragment = activeFragment;
let originalValue = value;
61
updateTime(originalValue);
}
}
playLoop() {
updateTime(currentTime);
activeFragment.play(0);
updateTime();
}
}
}
play() {
if (!playing) {
Play.innerText = "pause";
pause() {
if (playing) {
Play.innerText = "play_arrow";
clearInterval(playing);
activeFragment.pause();
delete playing;
}
}
63
updateTime(value) {
if (value === undefined)
value = currentTime;
if (activeFragment) {
let thumbPercentage = activeFragment.currentTime / activeFragment.duration
* 100;
activeFragment.thumbnailSeeker.style.left = `calc(${thumbPercentage}% -
2px)`;
BoostIn.value = activeFragment.playbackSpeed;
VolIn.value = activeFragment.volume * 100;
}
updateBottomInfo();
}
static secondsToHms(seconds) {
let stamp = new Date();
stamp.setTime(seconds * 1000);
64
let h = stamp.getHours();
let m = stamp.getMinutes();
m = m < 10 ? '0' + m : m;
let s = stamp.getSeconds();
s = s < 10 ? '0' + s : s;
return hms;
}
static hmsToSeconds(hms) {
let [h, m, s] = hms.split(':');
return Number(h) * 3600 + Number(m) * 60 + Number(s);
}
get duration() {
let duration = 0;
for (let fragment of fragments) {
duration += fragment.duration;
}
return duration;
65
addFragments(...files) {
if (files[0] instanceof FileList)
files = files[0];
loaded = 0;
toLoad = files.length;
isValidPath(path) {
let allowed = ['mp4', 'avi', 'webm', 'flv'];
for (let format of allowed)
if (path.toLowerCase().includes(format))
return true;
return false;
}
addFragmentByPath(path) {
if (!isValidPath(path))
return console.error("Path is not a valid video file");
let fragment = new VideoFragment(path, thumbnailZoom);
new AddFragment(this, fragment).execute();
}
set thumbnailZoom(value) {
_thumbnailZoom = value;
66
get thumbnailZoom() {
return _thumbnailZoom;
}
nextFrame() {
pause();
currentTime += 1 / activeFragment.fps;
}
previousFrame() {
pause();
currentTime -= 1 / activeFragment.fps;
}
get currentTime() {
let time = 0;
for (let fragment of fragments) {
if (fragment === activeFragment) {
return time + fragment.currentTime;
}
time += fragment.duration;
}
67
set activeFragment(value) {
if (value !== undefined) {
if (_activeFragment !== undefined && _activeFragment !== value)
_activeFragment.active = false;
value.active = true;
}
updateBottomInfo();
_activeFragment = value;
}
updateBottomInfo() {
if (activeFragment) {
FPSelement.innerText = "Frame rate: " + activeFragment.fps;
DurationOf.innerText = "Duration: " +
Video.secondsToHms(activeFragment.duration);
BoostSpeed.innerText = `Playback speed: $
{activeFragment.playbackSpeed}x`;
Volumepref.innerText = `Volume: ${Math.round(activeFragment.volume *
100)}%`;
}
}
get activeFragment() {
return _activeFragment;
}
upload({
68
config = ExportConfig.default,
title = 'Uploaded with VideoEditor',
description = 'https://github.com/RuurdBijlsma/Ruurd-Movie-Maker',
publicity = 'public',
onProgress = console.log
}) {
return new Promise(resolve => {
let format = 'mp4';
let tmpFile = `${tmpDir}/toUpload.${format}`;
let progress = 0;
let tokens;
Youtube.getAccessToken().then(t => {
tokens = t;
});
export({
config: config,
overwrite: true,
outputFile: tmpFile,
clearTmpDir: false,
onProgress: p => {
progress = p / 2;
onProgress(progress);
}
}).then(() => {
let startUpload = () => {
Youtube.upload({
path: tmpFile,
title: title,
description: description,
publicity: publicity,
69
onProgress: p => {
progress = 0.5 + p / 2;
onProgress(progress);
},
tokens: tokens,
}).then(e => {
resolve(e);
node.deleteDirectory(tmpDir);
});
};
if (!tokens) {
let checkUpload = self.setInterval(() => {
if (tokens) {
startUpload();
clearInterval(checkUpload);
}
console.log('Waiting for user...');
}, 100);
} else
startUpload();
});
});
}
export({
config = ExportConfig.default,
overwrite = true,
outputFile = 'output',
clearTmpDir = true,
onProgress = () => {
70
}
}) {
return new Promise(resolve => {
let i = 0;
let secondsProcessed = [];
let fragmentsToProcess = fragments.length;
let duration = duration;
node.clearDirectory(tmpDir);
element = document.createElement("video");
element.src = path;
element.load();
thumbnailElement = document.createElement("div");
thumbnailElement.setAttribute("class", "thumbnail");
thumbnailSeeker = document.createElement('div');
thumbnailSeeker.setAttribute("class", "thumbnail-seeker");
thumbnailElement.appendChild(thumbnailSeeker);
let innerSeeker = document.createElement('div');
innerSeeker.setAttribute("class", "thumbnail-inner-seeker");
72
thumbnailSeeker.appendChild(innerSeeker);
metadataLoaded = false;
element.onloadedmetadata = () => {
metadataLoaded = true;
executeEvent("loadedMetadata");
};
element.onloadeddata = () => {
executeEvent("loadedData");
widthPerSecond = widthPerSecond;
updateThumbnail(startPoint);
};
active = false;
startPoint = 0;
endPoint = 1;
playbackSpeed = 1;
updateFps();
}
timeToPoint(time) {
return startPoint + (time / durationWithoutEndTime) * (1 - startPoint);
}
get currentPoint() {
return timeToPoint(currentTime);
73
set active(value) {
_active = value;
if (value) {
element.style.zIndex = 1;
thumbnailElement.setAttribute("active", "");
executeEvent("timeChange");
} else {
element.style.zIndex = 0;
thumbnailElement.removeAttribute("active");
currentTime = 0;
pause();
}
}
get active() {
return _active;
}
addEventListener(name, action) {
if (!eventListeners[name])
eventListeners[name] = [];
eventListeners[name].push(action);
}
executeEvent(name) {
if (eventListeners.hasOwnProperty(name))
for (let action of eventListeners[name])
74
action();
}
get thumbnail() {
if (_thumbnail) {
return _thumbnail;
}
console.warn("Thumbnail hasn't loaded yet");
return null;
}
get exportStartTime() {
if (metadataLoaded) {
return startPoint * (element.duration /* / playbackSpeed*/);
}
console.warn("Video metadata hasn't loaded yet");
return 0;
}
get duration() {
if (metadataLoaded) {
return (endPoint - startPoint) * (element.duration / playbackSpeed);
}
console.warn("Video metadata hasn't loaded yet");
return 0;
}
get durationWithoutEndTime() {
if (metadataLoaded) {
return (1 - startPoint) * (element.duration / playbackSpeed);
75
}
console.warn("Video metadata hasn't loaded yet");
return 0;
}
get fps() {
return _fps * playbackSpeed;
}
updateFps() {
FFMPEG.runCommand(['-i', path]).then(info => {
let words = info.stderr.split('\n').find(line => line.includes(' fps')).split(' fps')
[0].split(' ');
_fps = Number(words[words.length - 1]);
executeEvent("loadedFps");
});
}
updateThumbnail(timePercentage = 0) {
getThumbnail(80, timePercentage).then(url => {
executeEvent("thumbnail");
thumbnailElement.style.backgroundImage = `url('${thumbnail}')`;
});
}
if (!isNaN(element.duration))
element.currentTime = timePercentage * element.duration;
element.oncanplaythrough = () => {
setTimeout(() => {
context.width = height / element.videoHeight * element.videoWidth;
context.height = height;
canvas.setAttribute("width", context.width);
canvas.setAttribute("height", context.height);
updateThumbnailWidth() {
thumbnailElement.style.width = thumbnailWidth + "px";
executeEvent("timeChange");
}
77
get volume() {
return element.volume;
}
set volume(value) {
if (value < 0 || value > 1)
console.warn("Value must be within range [0-1]");
element.volume = value;
executeEvent("timeChange");
}
get playbackSpeed() {
return _playbackSpeed;
}
set playbackSpeed(value) {
_playbackSpeed = value;
element.playbackRate = value;
updateThumbnailWidth();
}
get startPoint() {
return _startTime;
}
set startPoint(value) {
if (value < 0) {
console.warn("startPoint can't be lower than 0");
return;
78
_startTime = value;
updateThumbnailWidth();
}
get endPoint() {
return _endTime;
}
set endPoint(value) {
if (value > 1) {
console.warn("endPoint can't be higher than the video duration");
return;
}
_endTime = value;
updateThumbnailWidth();
}
get widthPerSecond() {
return _widthPerSecond;
}
set widthPerSecond(value) {
_widthPerSecond = value;
79
updateThumbnailWidth();
}
play(from) {
if (from !== undefined) {
currentTime = from;
}
if (element.paused)
element.play();
}
pause() {
element.pause();
}
get currentTime() {
let point = durationWithoutEndTime * (startPoint * element.duration -
element.currentTime);
point /= (startPoint - 1) * element.duration;
return point;
}
set currentTime(value) {
let point = timeToPoint(value);
point *= element.duration;
if (!isNaN(point))
element.currentTime = point;
}
80
export({
outputFile = 'output.mp4',
fps = null,
process = s => console.log(s),
}) {
let f = new FFMPEG();
f.input = path;
f.output = outputFile;
f.startTime = exportStartTime;
console.log("Exporting", exportStartTime);
f.overwrite = true;
if (duration !== element.duration)
f.duration = duration;
if (fps !== fps && fps !== null)
f.frameRate = fps;
if (playbackSpeed !== 1)
f.playbackSpeed = playbackSpeed;
if (volume !== 1)
f.volume = volume;
console.log(f);