Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding support for images, any maybe other file types? 😄 #754

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion interfaces/final-object.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ export type AllowedScreenshotHeight = 144 | 216 | 288 | 360 | 432 | 504;

export type ResolutionString = '' | 'SD' | '720' | '720+' | '1080' | '1080+' | '4K' | '4K+';

export type FileType = 'video' | 'image';

export interface SourceFolder {
path: string;
watch: boolean;
Expand All @@ -25,12 +27,13 @@ export interface FinalObject {
}

export interface ImageElement {
type: FileType; // type of file
birthtime: number; // file creation time
cleanName: string; // file name cleaned of dots, underscores,and file extension; for searching. Can be *FOLDER* sometimes
duration: number; // number of seconds - duration of film
fileName: string; // full file name with extension - for opening the file
fileSize: number; // file size in bytes
bitrate: number; // bitrate of the displayed video file - (fileSize/duration)*1024
bitrate: number; // bitrate of the displayed video file - (fileSize/duration)*1024
fps: number; // base frame rate of the video in fps
hash: string; // used for detecting changed files and as a screenshot identifier
height: AllowedScreenshotHeight; // height of the video (px)
Expand Down Expand Up @@ -67,6 +70,7 @@ export interface ImageElementPlus extends ImageElement {
// Use this to create a new ImageElement if needed
export function NewImageElement(): ImageElement {
return {
type: 'video',
birthtime: 0,
cleanName: '',
duration: 0,
Expand Down
6 changes: 3 additions & 3 deletions node/main-extract-async.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { fdir } from 'fdir';
import { GLOBALS } from './main-globals';

import type { ImageElement, ImageElementPlus } from '../interfaces/final-object.interface';
import { acceptableFiles } from './main-filenames';
import { acceptableImageFiles, acceptableVideoFiles } from './main-filenames';
import { extractAll } from './main-extract';
import { sendCurrentProgress, insertTemporaryFieldsSingle, extractMetadataAsync, cleanUpFileName } from './main-support';

Expand Down Expand Up @@ -238,7 +238,7 @@ function superFastSystemScan(inputDir: string, inputSource: number): void {
console.log('Found ', files.length, ' files in given directory');
// =============================================================================================

const allAcceptableFiles: string[] = [...acceptableFiles, ...GLOBALS.additionalExtensions];
const allAcceptableFiles: string[] = [...acceptableVideoFiles, ...acceptableImageFiles, ...GLOBALS.additionalExtensions];

files.forEach((fullPath: string) => {

Expand Down Expand Up @@ -315,7 +315,7 @@ export function startFileSystemWatching(inputDir: string, inputSource: number, p

const watcher: FSWatcher = chokidar.watch(inputDir, watcherConfig);

const allAcceptableFiles: string[] = [...acceptableFiles, ...GLOBALS.additionalExtensions];
const allAcceptableFiles: string[] = [...acceptableVideoFiles, ...acceptableImageFiles, ...GLOBALS.additionalExtensions];

metadataQueue.pause();
thumbQueue.pause();
Expand Down
22 changes: 19 additions & 3 deletions node/main-extract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const ffmpegPath = require('ffmpeg-static').replace('app.asar', 'app.asar.unpack
import { GLOBALS } from './main-globals';

import type { ImageElement, ScreenshotSettings } from '../interfaces/final-object.interface';
import { acceptableImageFiles } from './main-filenames';


// ========================================================================================
Expand All @@ -44,16 +45,26 @@ import type { ImageElement, ScreenshotSettings } from '../interfaces/final-objec
* @param savePath
*/
const extractSingleFrameArgs = (
currentElement: ImageElement,
pathToVideo: string,
screenshotHeight: number,
duration: number,
savePath: string,
): string[] => {

const ssWidth: number = screenshotHeight * (16 / 9);

if (currentElement.type == 'image') {
const args: string[] = [
'-i', pathToVideo,
'-q:v', '2',
'-vf', scaleAndPadString(ssWidth, screenshotHeight),
savePath,
];
return args;
}

const args: string[] = [
'-ss', (duration / 10).toString(),
'-ss', (currentElement.duration / 10).toString(),
'-i', pathToVideo,
'-frames', '1',
'-q:v', '2',
Expand Down Expand Up @@ -280,7 +291,7 @@ export function extractAll(
return true;
} else {
const ffmpegArgs: string[] = extractSingleFrameArgs(
pathToVideo, screenshotHeight, duration, thumbnailSavePath
currentElement, pathToVideo, screenshotHeight, thumbnailSavePath
);

return spawn_ffmpeg_and_run(ffmpegArgs, maxRunTime.thumb, 'thumb'); // (3)
Expand All @@ -292,6 +303,11 @@ export function extractAll(
if (!thumbSuccess) {
throw new Error('SINGLE SCREENSHOT EXTRACTION TIMED OUT - LIKELY CORRUPT');
} else {
if (currentElement.type == 'image') {
// Bale out early, images don't need anything else
done();
return;
}
return checkFileExists(filmstripSavePath); // (4)
}
})
Expand Down
6 changes: 5 additions & 1 deletion node/main-filenames.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export const acceptableFiles = [
export const acceptableVideoFiles = [
'264',
'265',
'3g2',
Expand Down Expand Up @@ -32,3 +32,7 @@ export const acceptableFiles = [
'webm',
'wmv'
];

export const acceptableImageFiles = [
'jpg'
];
16 changes: 14 additions & 2 deletions node/main-support.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ const fs = require('fs');
const hasher = require('crypto').createHash;
import type { Stats } from 'fs';

import type { FinalObject, ImageElement, ScreenshotSettings, InputSources, ResolutionString} from '../interfaces/final-object.interface';
import type { FinalObject, ImageElement, ScreenshotSettings, InputSources, ResolutionString, FileType} from '../interfaces/final-object.interface';
import { NewImageElement } from '../interfaces/final-object.interface';
import { startFileSystemWatching, resetWatchers } from './main-extract-async';
import { acceptableImageFiles, acceptableVideoFiles } from './main-filenames';

interface ResolutionMeta {
label: ResolutionString;
Expand Down Expand Up @@ -305,7 +306,7 @@ function getBestStream(metadata) {
*/
function getFileDuration(metadata): number {
if (metadata?.streams?.[0]?.duration) {

return metadata.streams[0].duration;

} else if (metadata?.format?.duration) {
Expand Down Expand Up @@ -451,12 +452,14 @@ export function extractMetadataAsync(
const origWidth = stream.width || 0; // ffprobe does not detect it on some MKV streams
const origHeight = stream.height || 0;


fs.stat(filePath, (err2, fileStat) => {
if (err2) {
reject();
}

const imageElement = NewImageElement();
imageElement.type = getFileType(filePath);
imageElement.birthtime = Math.round(fileStat.birthtimeMs);
imageElement.duration = duration;
imageElement.fileSize = fileStat.size;
Expand All @@ -478,6 +481,15 @@ export function extractMetadataAsync(
});
}

export function getFileType(filePath: string): FileType {
const fileExtension = path.parse(filePath).ext.substr(1).toLowerCase();
if (acceptableVideoFiles.includes(fileExtension)) {
return 'video';
} else if (acceptableImageFiles.includes(fileExtension)) {
return 'image';
}
}

/**
* Sends progress to Angular App
* @param current number
Expand Down
6 changes: 5 additions & 1 deletion src/app/components/views/details/details.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,11 @@ export class DetailsComponent implements OnInit {

ngOnInit() {
this.firstFilePath = this.filePathService.createFilePath(this.folderPath, this.hubName, 'thumbnails', this.video.hash);
this.filmstripPath = this.filePathService.createFilePath(this.folderPath, this.hubName, 'filmstrips', this.video.hash);
if (this.video.type == 'image') {
this.filmstripPath = this.firstFilePath;
} else {
this.filmstripPath = this.filePathService.createFilePath(this.folderPath, this.hubName, 'filmstrips', this.video.hash);
}
if (this.video.defaultScreen !== undefined) {
this.percentOffset = this.getDefaultScreenOffset(this.video);
}
Expand Down
6 changes: 5 additions & 1 deletion src/app/components/views/filmstrip/filmstrip.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,11 @@ export class FilmstripComponent implements OnInit {
) { }

ngOnInit() {
this.fullFilePath = this.filePathService.createFilePath(this.folderPath, this.hubName, 'filmstrips', this.video.hash);
if (this.video.type == 'image') {
this.fullFilePath = this.filePathService.createFilePath(this.folderPath, this.hubName, 'thumbnails', this.video.hash);
} else {
this.fullFilePath = this.filePathService.createFilePath(this.folderPath, this.hubName, 'filmstrips', this.video.hash);
}
}

updateFilmXoffset($event) {
Expand Down
7 changes: 5 additions & 2 deletions src/app/components/views/full/full.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,11 @@ export class FullViewComponent implements OnInit {
) { }

ngOnInit() {
this.fullFilePath = this.filePathService.createFilePath(this.folderPath, this.hubName, 'filmstrips', this.video.hash);
this.render();
if (this.video.type == 'image') {
this.fullFilePath = this.filePathService.createFilePath(this.folderPath, this.hubName, 'thumbnails', this.video.hash);
} else {
this.fullFilePath = this.filePathService.createFilePath(this.folderPath, this.hubName, 'filmstrips', this.video.hash);
} this.render();
}

render(): void {
Expand Down
6 changes: 5 additions & 1 deletion src/app/components/views/thumbnail/thumbnail.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,11 @@ export class ThumbnailComponent implements OnInit, OnDestroy {
});
} else {
this.firstFilePath = this.filePathService.createFilePath(this.folderPath, this.hubName, 'thumbnails', this.video.hash);
this.fullFilePath = this.filePathService.createFilePath(this.folderPath, this.hubName, 'filmstrips', this.video.hash);
if (this.video.type == 'image') {
this.fullFilePath = this.firstFilePath;
} else {
this.fullFilePath = this.filePathService.createFilePath(this.folderPath, this.hubName, 'filmstrips', this.video.hash);
}
this.folderThumbPaths.push(this.firstFilePath);
}

Expand Down