mirror of
https://github.com/bpatrik/pigallery2.git
synced 2025-02-11 13:53:28 +02:00
improving video support
This commit is contained in:
parent
4a7e91ceb3
commit
ad7225c62e
@ -5,7 +5,7 @@ import {Logger} from '../Logger';
|
||||
import {SQLConnection} from '../model/sql/SQLConnection';
|
||||
import {DataBaseConfig, DatabaseType, IndexingConfig, IPrivateConfig, ThumbnailConfig} from '../../common/config/private/IPrivateConfig';
|
||||
import {Config} from '../../common/config/private/Config';
|
||||
import {ConfigDiagnostics} from '../model/ConfigDiagnostics';
|
||||
import {ConfigDiagnostics} from '../model/diagnostics/ConfigDiagnostics';
|
||||
import {ClientConfig} from '../../common/config/public/ConfigClass';
|
||||
import {BasicConfigDTO} from '../../common/entities/settings/BasicConfigDTO';
|
||||
import {OtherConfigDTO} from '../../common/entities/settings/OtherConfigDTO';
|
||||
@ -80,6 +80,27 @@ export class AdminMWs {
|
||||
return next(new ErrorDTO(ErrorCodes.SETTINGS_ERROR, 'Settings error: ' + JSON.stringify(err, null, ' '), err));
|
||||
}
|
||||
}
|
||||
public static async updateVideoSettings(req: Request, res: Response, next: NextFunction) {
|
||||
if ((typeof req.body === 'undefined') || (typeof req.body.settings === 'undefined')) {
|
||||
return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, 'settings is needed'));
|
||||
}
|
||||
|
||||
try {
|
||||
await ConfigDiagnostics.testVideoConfig(<ClientConfig.VideoConfig>req.body.settings);
|
||||
|
||||
Config.Client.Video = <ClientConfig.VideoConfig>req.body.settings;
|
||||
// only updating explicitly set config (not saving config set by the diagnostics)
|
||||
const original = Config.original();
|
||||
original.Client.Video = <ClientConfig.VideoConfig>req.body.settings;
|
||||
original.save();
|
||||
await ConfigDiagnostics.runDiagnostics();
|
||||
Logger.info(LOG_TAG, 'new config:');
|
||||
Logger.info(LOG_TAG, JSON.stringify(Config, null, '\t'));
|
||||
return next();
|
||||
} catch (err) {
|
||||
return next(new ErrorDTO(ErrorCodes.SETTINGS_ERROR, 'Settings error: ' + err.toString(), err));
|
||||
}
|
||||
}
|
||||
|
||||
public static async updateShareSettings(req: Request, res: Response, next: NextFunction) {
|
||||
if ((typeof req.body === 'undefined') || (typeof req.body.settings === 'undefined')) {
|
||||
|
@ -52,7 +52,7 @@ export class GalleryMWs {
|
||||
}
|
||||
|
||||
|
||||
public static removeCyclicDirectoryReferences(req: Request, res: Response, next: NextFunction) {
|
||||
public static cleanUpGalleryResults(req: Request, res: Response, next: NextFunction) {
|
||||
if (!req.resultPipe) {
|
||||
return next();
|
||||
}
|
||||
@ -61,17 +61,6 @@ export class GalleryMWs {
|
||||
if (cw.notModified === true) {
|
||||
return next();
|
||||
}
|
||||
const removeDirs = (dir: DirectoryDTO) => {
|
||||
dir.media.forEach((photo: PhotoDTO) => {
|
||||
photo.directory = null;
|
||||
});
|
||||
|
||||
dir.directories.forEach((directory: DirectoryDTO) => {
|
||||
removeDirs(directory);
|
||||
directory.parent = null;
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
const cleanUpMedia = (media: MediaDTO[]) => {
|
||||
media.forEach(m => {
|
||||
@ -89,7 +78,7 @@ export class GalleryMWs {
|
||||
};
|
||||
|
||||
if (cw.directory) {
|
||||
removeDirs(cw.directory);
|
||||
DirectoryDTO.removeReferences(cw.directory);
|
||||
// TODO: remove when typeorm inheritance is fixed
|
||||
cleanUpMedia(cw.directory.media);
|
||||
}
|
||||
@ -98,6 +87,19 @@ export class GalleryMWs {
|
||||
}
|
||||
|
||||
|
||||
if (Config.Client.Video.enabled === false) {
|
||||
if (cw.directory) {
|
||||
const removeVideos = (dir: DirectoryDTO) => {
|
||||
dir.media = dir.media.filter(m => !MediaDTO.isVideo(m));
|
||||
dir.directories.forEach(d => removeVideos(d));
|
||||
};
|
||||
removeVideos(cw.directory);
|
||||
}
|
||||
if (cw.searchResult) {
|
||||
cw.searchResult.media = cw.searchResult.media.filter(m => !MediaDTO.isVideo(m));
|
||||
}
|
||||
}
|
||||
|
||||
return next();
|
||||
}
|
||||
|
||||
|
13
backend/model/FFmpegFactory.ts
Normal file
13
backend/model/FFmpegFactory.ts
Normal file
@ -0,0 +1,13 @@
|
||||
export class FFmpegFactory {
|
||||
public static get() {
|
||||
const ffmpeg = require('fluent-ffmpeg');
|
||||
try {
|
||||
const ffmpegPath = require('@ffmpeg-installer/ffmpeg').path;
|
||||
ffmpeg.setFfmpegPath(ffmpegPath);
|
||||
const ffprobePath = require('@ffprobe-installer/ffprobe').path;
|
||||
ffmpeg.setFfprobePath(ffprobePath);
|
||||
} catch (e) {
|
||||
}
|
||||
return ffmpeg;
|
||||
}
|
||||
}
|
@ -1,17 +1,19 @@
|
||||
import {Config} from '../../common/config/private/Config';
|
||||
import {Config} from '../../../common/config/private/Config';
|
||||
import {
|
||||
DataBaseConfig,
|
||||
DatabaseType,
|
||||
IPrivateConfig,
|
||||
ThumbnailConfig,
|
||||
ThumbnailProcessingLib
|
||||
} from '../../common/config/private/IPrivateConfig';
|
||||
import {Logger} from '../Logger';
|
||||
import {NotificationManager} from './NotifocationManager';
|
||||
import {ProjectPath} from '../ProjectPath';
|
||||
import {SQLConnection} from './sql/SQLConnection';
|
||||
} from '../../../common/config/private/IPrivateConfig';
|
||||
import {Logger} from '../../Logger';
|
||||
import {NotificationManager} from '../NotifocationManager';
|
||||
import {ProjectPath} from '../../ProjectPath';
|
||||
import {SQLConnection} from '../sql/SQLConnection';
|
||||
import * as fs from 'fs';
|
||||
import {ClientConfig} from '../../common/config/public/ConfigClass';
|
||||
import {ClientConfig} from '../../../common/config/public/ConfigClass';
|
||||
import VideoConfig = ClientConfig.VideoConfig;
|
||||
import {FFmpegFactory} from '../FFmpegFactory';
|
||||
|
||||
const LOG_TAG = '[ConfigDiagnostics]';
|
||||
|
||||
@ -24,6 +26,31 @@ export class ConfigDiagnostics {
|
||||
}
|
||||
|
||||
|
||||
static testVideoConfig(videoConfig: VideoConfig) {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
if (videoConfig.enabled === true) {
|
||||
const ffmpeg = FFmpegFactory.get();
|
||||
ffmpeg().getAvailableCodecs((err) => {
|
||||
if (err) {
|
||||
return reject(new Error('Error accessing ffmpeg, cant find executable: ' + err.toString()));
|
||||
}
|
||||
ffmpeg(__dirname + '/blank.jpg').ffprobe((err2) => {
|
||||
if (err2) {
|
||||
return reject(new Error('Error accessing ffmpeg-probe, cant find executable: ' + err2.toString()));
|
||||
}
|
||||
return resolve();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
return resolve();
|
||||
}
|
||||
} catch (e) {
|
||||
return reject(new Error('unkown video error: ' + e.toString()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static async testThumbnailLib(processingLibrary: ThumbnailProcessingLib) {
|
||||
switch (processingLibrary) {
|
||||
case ThumbnailProcessingLib.sharp:
|
||||
@ -44,8 +71,8 @@ export class ConfigDiagnostics {
|
||||
}
|
||||
}
|
||||
|
||||
static async testThumbnailFolder(folder: string) {
|
||||
await new Promise((resolve, reject) => {
|
||||
static testThumbnailFolder(folder: string) {
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.access(folder, fs.constants.W_OK, (err) => {
|
||||
if (err) {
|
||||
reject({message: 'Error during getting write access to temp folder', error: err.toString()});
|
||||
@ -55,8 +82,8 @@ export class ConfigDiagnostics {
|
||||
});
|
||||
}
|
||||
|
||||
static async testImageFolder(folder: string) {
|
||||
await new Promise((resolve, reject) => {
|
||||
static testImageFolder(folder: string) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!fs.existsSync(folder)) {
|
||||
reject('Images folder not exists: \'' + folder + '\'');
|
||||
}
|
||||
@ -164,6 +191,16 @@ export class ConfigDiagnostics {
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
await ConfigDiagnostics.testVideoConfig(Config.Client.Video);
|
||||
} catch (ex) {
|
||||
const err: Error = ex;
|
||||
NotificationManager.warning('Video support error, switching off..', err.toString());
|
||||
Logger.warn(LOG_TAG, 'Video support error, switching off..', err.toString());
|
||||
Config.Client.Video.enabled = false;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
await ConfigDiagnostics.testImageFolder(Config.Server.imagesFolder);
|
||||
} catch (ex) {
|
BIN
backend/model/diagnostics/blank.jpg
Normal file
BIN
backend/model/diagnostics/blank.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 631 B |
@ -17,7 +17,7 @@ import {VideoEntity} from './enitites/VideoEntity';
|
||||
|
||||
export class SQLConnection {
|
||||
|
||||
private static VERSION = 1;
|
||||
private static VERSION = 2;
|
||||
|
||||
constructor() {
|
||||
}
|
||||
|
@ -5,15 +5,17 @@ import {CameraMetadata, GPSMetadata, PhotoDTO, PhotoMetadata} from '../../../com
|
||||
import {Logger} from '../../Logger';
|
||||
import {IptcParser} from 'ts-node-iptc';
|
||||
import {ExifParserFactory, OrientationTypes} from 'ts-exif-parser';
|
||||
import * as ffmpeg from 'fluent-ffmpeg';
|
||||
import {FfprobeData} from 'fluent-ffmpeg';
|
||||
import {ProjectPath} from '../../ProjectPath';
|
||||
import {Config} from '../../../common/config/private/Config';
|
||||
import {VideoDTO, VideoMetadata} from '../../../common/entities/VideoDTO';
|
||||
import {MediaDimension, MediaMetadata} from '../../../common/entities/MediaDTO';
|
||||
import {MediaDimension} from '../../../common/entities/MediaDTO';
|
||||
import {FFmpegFactory} from '../FFmpegFactory';
|
||||
|
||||
const LOG_TAG = '[DiskManagerTask]';
|
||||
|
||||
const ffmpeg = FFmpegFactory.get();
|
||||
|
||||
export class DiskMangerWorker {
|
||||
private static isImage(fullPath: string) {
|
||||
const extensions = [
|
||||
@ -33,8 +35,7 @@ export class DiskMangerWorker {
|
||||
|
||||
private static isVideo(fullPath: string) {
|
||||
const extensions = [
|
||||
'.mp4',
|
||||
'.webm'
|
||||
'.mp4'
|
||||
];
|
||||
|
||||
const extension = path.extname(fullPath).toLowerCase();
|
||||
@ -83,7 +84,8 @@ export class DiskMangerWorker {
|
||||
if (maxPhotos != null && directory.media.length > maxPhotos) {
|
||||
break;
|
||||
}
|
||||
} else if (DiskMangerWorker.isVideo(fullFilePath)) {
|
||||
} else if (Config.Client.Video.enabled === true &&
|
||||
DiskMangerWorker.isVideo(fullFilePath)) {
|
||||
directory.media.push(<VideoDTO>{
|
||||
name: file,
|
||||
directory: null,
|
||||
@ -98,7 +100,7 @@ export class DiskMangerWorker {
|
||||
|
||||
return resolve(directory);
|
||||
} catch (err) {
|
||||
return reject({error: err});
|
||||
return reject({error: err.toString()});
|
||||
}
|
||||
|
||||
});
|
||||
|
@ -3,6 +3,7 @@ import {Dimensions, State} from 'gm';
|
||||
import {Logger} from '../../Logger';
|
||||
import {FfmpegCommand, FfprobeData} from 'fluent-ffmpeg';
|
||||
import {ThumbnailProcessingLib} from '../../../common/config/private/IPrivateConfig';
|
||||
import {FFmpegFactory} from '../FFmpegFactory';
|
||||
|
||||
export class ThumbnailWorker {
|
||||
|
||||
@ -50,7 +51,7 @@ export interface RendererInput {
|
||||
|
||||
export class VideoRendererFactory {
|
||||
public static build(): (input: RendererInput) => Promise<void> {
|
||||
const ffmpeg = require('fluent-ffmpeg');
|
||||
const ffmpeg = FFmpegFactory.get();
|
||||
return (input: RendererInput): Promise<void> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
|
@ -59,6 +59,12 @@ export class AdminRouter {
|
||||
AdminMWs.updateMapSettings,
|
||||
RenderingMWs.renderOK
|
||||
);
|
||||
app.put('/api/settings/video',
|
||||
AuthenticationMWs.authenticate,
|
||||
AuthenticationMWs.authorise(UserRoles.Admin),
|
||||
AdminMWs.updateVideoSettings,
|
||||
RenderingMWs.renderOK
|
||||
);
|
||||
|
||||
app.put('/api/settings/authentication',
|
||||
AuthenticationMWs.authenticate,
|
||||
|
@ -27,7 +27,7 @@ export class GalleryRouter {
|
||||
AuthenticationMWs.authoriseDirectory,
|
||||
GalleryMWs.listDirectory,
|
||||
ThumbnailGeneratorMWs.addThumbnailInformation,
|
||||
GalleryMWs.removeCyclicDirectoryReferences,
|
||||
GalleryMWs.cleanUpGalleryResults,
|
||||
RenderingMWs.renderResult
|
||||
);
|
||||
}
|
||||
@ -98,7 +98,7 @@ export class GalleryRouter {
|
||||
AuthenticationMWs.authorise(UserRoles.Guest),
|
||||
GalleryMWs.search,
|
||||
ThumbnailGeneratorMWs.addThumbnailInformation,
|
||||
GalleryMWs.removeCyclicDirectoryReferences,
|
||||
GalleryMWs.cleanUpGalleryResults,
|
||||
RenderingMWs.renderResult
|
||||
);
|
||||
}
|
||||
@ -109,7 +109,7 @@ export class GalleryRouter {
|
||||
AuthenticationMWs.authorise(UserRoles.Guest),
|
||||
GalleryMWs.instantSearch,
|
||||
ThumbnailGeneratorMWs.addThumbnailInformation,
|
||||
GalleryMWs.removeCyclicDirectoryReferences,
|
||||
GalleryMWs.cleanUpGalleryResults,
|
||||
RenderingMWs.renderResult
|
||||
);
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ import {LoggerRouter} from './routes/LoggerRouter';
|
||||
import {ThumbnailGeneratorMWs} from './middlewares/thumbnail/ThumbnailGeneratorMWs';
|
||||
import {DiskManager} from './model/DiskManger';
|
||||
import {NotificationRouter} from './routes/NotificationRouter';
|
||||
import {ConfigDiagnostics} from './model/ConfigDiagnostics';
|
||||
import {ConfigDiagnostics} from './model/diagnostics/ConfigDiagnostics';
|
||||
import {Localizations} from './model/Localizations';
|
||||
import {CookieNames} from '../common/CookieNames';
|
||||
|
||||
|
@ -43,6 +43,11 @@ export module ClientConfig {
|
||||
NavBar: NavBarConfig;
|
||||
}
|
||||
|
||||
export interface VideoConfig {
|
||||
enabled: boolean;
|
||||
}
|
||||
|
||||
|
||||
export interface Config {
|
||||
applicationTitle: string;
|
||||
publicUrl: string;
|
||||
@ -55,6 +60,7 @@ export module ClientConfig {
|
||||
Other: OtherConfig;
|
||||
authenticationRequired: boolean;
|
||||
languages: string[];
|
||||
Video: VideoConfig;
|
||||
}
|
||||
|
||||
}
|
||||
@ -91,6 +97,9 @@ export class PublicConfigClass {
|
||||
RandomPhoto: {
|
||||
enabled: true
|
||||
},
|
||||
Video: {
|
||||
enabled: true
|
||||
},
|
||||
Other: {
|
||||
enableCache: true,
|
||||
enableOnScrollRendering: true,
|
||||
|
@ -1,4 +1,5 @@
|
||||
import {MediaDTO} from './MediaDTO';
|
||||
import {PhotoDTO} from './PhotoDTO';
|
||||
|
||||
export interface DirectoryDTO {
|
||||
id: number;
|
||||
@ -23,4 +24,16 @@ export module DirectoryDTO {
|
||||
directory.parent = dir;
|
||||
});
|
||||
};
|
||||
|
||||
export const removeReferences = (dir: DirectoryDTO) => {
|
||||
dir.media.forEach((photo: PhotoDTO) => {
|
||||
photo.directory = null;
|
||||
});
|
||||
|
||||
dir.directories.forEach((directory: DirectoryDTO) => {
|
||||
removeReferences(directory);
|
||||
directory.parent = null;
|
||||
});
|
||||
|
||||
};
|
||||
}
|
||||
|
@ -43,13 +43,15 @@
|
||||
<app-settings-database [simplifiedMode]="simplifiedMode"></app-settings-database>
|
||||
<app-settings-thumbnail #thumbnail [hidden]="!thumbnail.hasAvailableSettings"
|
||||
[simplifiedMode]="simplifiedMode"></app-settings-thumbnail>
|
||||
<app-settings-video #video [hidden]="!video.hasAvailableSettings"
|
||||
[simplifiedMode]="simplifiedMode"></app-settings-video>
|
||||
<app-settings-search #search [hidden]="!search.hasAvailableSettings"
|
||||
[simplifiedMode]="simplifiedMode"></app-settings-search>
|
||||
<app-settings-share #share [hidden]="!share.hasAvailableSettings"
|
||||
[simplifiedMode]="simplifiedMode"></app-settings-share>
|
||||
<app-settings-map #map [hidden]="!map.hasAvailableSettings" [simplifiedMode]="simplifiedMode"></app-settings-map>
|
||||
<app-settings-random-photo #random [hidden]="!random.hasAvailableSettings"
|
||||
[simplifiedMode]="simplifiedMode"></app-settings-random-photo>
|
||||
[simplifiedMode]="simplifiedMode"></app-settings-random-photo>
|
||||
<app-settings-other #other [hidden]="!other.hasAvailableSettings"
|
||||
[simplifiedMode]="simplifiedMode"></app-settings-other>
|
||||
<app-settings-indexing #indexing [hidden]="!indexing.hasAvailableSettings"
|
||||
|
@ -73,6 +73,7 @@ import {StringifySortingMethod} from './pipes/StringifySortingMethod';
|
||||
import {RandomQueryBuilderGalleryComponent} from './gallery/random-query-builder/random-query-builder.gallery.component';
|
||||
import {RandomPhotoSettingsComponent} from './settings/random-photo/random-photo.settings.component';
|
||||
import {FixOrientationPipe} from './gallery/FixOrientationPipe';
|
||||
import {VideoSettingsComponent} from './settings/video/video.settings.component';
|
||||
|
||||
@Injectable()
|
||||
export class GoogleMapsConfig {
|
||||
@ -159,6 +160,7 @@ export function translationsFactory(locale: string) {
|
||||
DatabaseSettingsComponent,
|
||||
MapSettingsComponent,
|
||||
ThumbnailSettingsComponent,
|
||||
VideoSettingsComponent,
|
||||
SearchSettingsComponent,
|
||||
ShareSettingsComponent,
|
||||
RandomPhotoSettingsComponent,
|
||||
|
@ -135,7 +135,7 @@ export abstract class SettingsComponent<T, S extends AbstractSettingsService<T>
|
||||
try {
|
||||
await this._settingsService.updateSettings(this.settings);
|
||||
await this.getSettings();
|
||||
this.notification.success(this.name + this.i18n(' settings saved'), this.i18n('Success'));
|
||||
this.notification.success(this.name + ' ' + this.i18n('settings saved'), this.i18n('Success'));
|
||||
this.inProgress = false;
|
||||
return true;
|
||||
} catch (err) {
|
||||
|
@ -16,9 +16,9 @@
|
||||
|
||||
<ng-container *ngIf="settings.type == DatabaseType.mysql">
|
||||
<p class="title" i18n>MySQL settings:</p>
|
||||
<input type="text" class="form-control" i18n-placeholder placeholder="Host" autofocus
|
||||
<input type="text" class="form-control" i18n-placeholder placeholder="Host"
|
||||
[(ngModel)]="settings.mysql.host" name="host" required>
|
||||
<input type="text" class="form-control" i18n-placeholder placeholder="Database" autofocus
|
||||
<input type="text" class="form-control" i18n-placeholder placeholder="Database"
|
||||
[(ngModel)]="settings.mysql.database" name="database" required>
|
||||
<input type="text" class="form-control" i18n-placeholder placeholder="Username"
|
||||
[(ngModel)]="settings.mysql.username" name="username">
|
||||
|
@ -36,6 +36,9 @@ export class SettingsService {
|
||||
RandomPhoto: {
|
||||
enabled: true
|
||||
},
|
||||
Video: {
|
||||
enabled: true
|
||||
},
|
||||
Other: {
|
||||
enableCache: true,
|
||||
enableOnScrollRendering: true,
|
||||
|
@ -74,7 +74,7 @@
|
||||
</div>
|
||||
<form #NewUserForm="ngForm">
|
||||
<div class="modal-body">
|
||||
<input type="text" class="form-control" i18n-placeholder placeholder="Username" autofocus
|
||||
<input type="text" class="form-control" i18n-placeholder placeholder="Username"
|
||||
[(ngModel)]="newUser.name" name="name" required>
|
||||
<input type="password" class="form-control" i18n-placeholder placeholder="Password"
|
||||
[(ngModel)]="newUser.password" name="password" required>
|
||||
|
36
frontend/app/settings/video/video.settings.component.html
Normal file
36
frontend/app/settings/video/video.settings.component.html
Normal file
@ -0,0 +1,36 @@
|
||||
<form #settingsForm="ngForm" class="form-horizontal">
|
||||
<div class="card mb-4">
|
||||
<h5 class="card-header">
|
||||
<ng-container i18n>Video settings</ng-container>
|
||||
<div class="switch-wrapper">
|
||||
<bSwitch
|
||||
class="switch"
|
||||
name="enabled"
|
||||
[switch-on-color]="'success'"
|
||||
[switch-inverse]="'inverse'"
|
||||
[switch-off-text]="text.Disabled"
|
||||
[switch-on-text]="text.Enabled"
|
||||
[switch-disabled]="inProgress"
|
||||
[switch-handle-width]="'100'"
|
||||
[switch-label-width]="'20'"
|
||||
[(ngModel)]="settings.enabled">
|
||||
</bSwitch>
|
||||
</div>
|
||||
</h5>
|
||||
<div class="card-body">
|
||||
<div [hidden]="!error" class="alert alert-danger" role="alert"><strong>Error: </strong>{{error}}</div>
|
||||
|
||||
<ng-container i18n>Video support uses ffmpeg. ffmpeg and ffprobe binaries need to be available in the PATH or the @ffmpeg-installer/ffmpeg and @ffprobe-installer/ffprobe optional node packages need to be installed.</ng-container>
|
||||
|
||||
|
||||
<button class="btn btn-success float-right"
|
||||
[disabled]="!settingsForm.form.valid || !changed || inProgress"
|
||||
(click)="save()" i18n>Save
|
||||
</button>
|
||||
<button class="btn btn-default float-right"
|
||||
(click)="reset()" i18n>Reset
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
32
frontend/app/settings/video/video.settings.component.ts
Normal file
32
frontend/app/settings/video/video.settings.component.ts
Normal file
@ -0,0 +1,32 @@
|
||||
import {Component} from '@angular/core';
|
||||
import {VideoSettingsService} from './video.settings.service';
|
||||
import {SettingsComponent} from '../_abstract/abstract.settings.component';
|
||||
import {AuthenticationService} from '../../model/network/authentication.service';
|
||||
import {NavigationService} from '../../model/navigation.service';
|
||||
import {NotificationService} from '../../model/notification.service';
|
||||
import {ClientConfig} from '../../../../common/config/public/ConfigClass';
|
||||
import {I18n} from '@ngx-translate/i18n-polyfill';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-settings-video',
|
||||
templateUrl: './video.settings.component.html',
|
||||
styleUrls: ['./video.settings.component.css',
|
||||
'./../_abstract/abstract.settings.component.css'],
|
||||
providers: [VideoSettingsService],
|
||||
})
|
||||
export class VideoSettingsComponent extends SettingsComponent<ClientConfig.VideoConfig> {
|
||||
|
||||
constructor(_authService: AuthenticationService,
|
||||
_navigation: NavigationService,
|
||||
_settingsService: VideoSettingsService,
|
||||
notification: NotificationService,
|
||||
i18n: I18n) {
|
||||
super(i18n('Video'), _authService, _navigation, <any>_settingsService, notification, i18n, s => s.Client.Video);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
19
frontend/app/settings/video/video.settings.service.ts
Normal file
19
frontend/app/settings/video/video.settings.service.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import {Injectable} from '@angular/core';
|
||||
import {NetworkService} from '../../model/network/network.service';
|
||||
import {ClientConfig} from '../../../../common/config/public/ConfigClass';
|
||||
import {SettingsService} from '../settings.service';
|
||||
import {AbstractSettingsService} from '../_abstract/abstract.settings.service';
|
||||
|
||||
@Injectable()
|
||||
export class VideoSettingsService extends AbstractSettingsService<ClientConfig.MapConfig> {
|
||||
constructor(private _networkService: NetworkService,
|
||||
_settingsService: SettingsService) {
|
||||
super(_settingsService);
|
||||
|
||||
}
|
||||
|
||||
public updateSettings(settings: ClientConfig.VideoConfig): Promise<void> {
|
||||
return this._networkService.putJson('/settings/video', {settings: settings});
|
||||
}
|
||||
|
||||
}
|
@ -104,7 +104,7 @@
|
||||
<source>download</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">app/gallery/lightbox/lightbox.gallery.component.html</context>
|
||||
<context context-type="linenumber">25</context>
|
||||
<context context-type="linenumber">27</context>
|
||||
</context-group>
|
||||
<target>download</target>
|
||||
</trans-unit>
|
||||
@ -112,7 +112,7 @@
|
||||
<source>info</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">app/gallery/lightbox/lightbox.gallery.component.html</context>
|
||||
<context context-type="linenumber">29</context>
|
||||
<context context-type="linenumber">31</context>
|
||||
</context-group>
|
||||
<target>info</target>
|
||||
</trans-unit>
|
||||
@ -120,11 +120,11 @@
|
||||
<source>toggle fullscreen</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">app/gallery/lightbox/lightbox.gallery.component.html</context>
|
||||
<context context-type="linenumber">36</context>
|
||||
<context context-type="linenumber">38</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">app/gallery/lightbox/lightbox.gallery.component.html</context>
|
||||
<context context-type="linenumber">45</context>
|
||||
<context context-type="linenumber">47</context>
|
||||
</context-group>
|
||||
<target>toggle fullscreen</target>
|
||||
</trans-unit>
|
||||
@ -132,7 +132,7 @@
|
||||
<source>close</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">app/gallery/lightbox/lightbox.gallery.component.html</context>
|
||||
<context context-type="linenumber">52</context>
|
||||
<context context-type="linenumber">54</context>
|
||||
</context-group>
|
||||
<target>close</target>
|
||||
</trans-unit>
|
||||
@ -140,7 +140,7 @@
|
||||
<source>key: left arrow</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">app/gallery/lightbox/lightbox.gallery.component.html</context>
|
||||
<context context-type="linenumber">60</context>
|
||||
<context context-type="linenumber">68</context>
|
||||
</context-group>
|
||||
<target>key: left arrow</target>
|
||||
</trans-unit>
|
||||
@ -148,7 +148,7 @@
|
||||
<source>key: right arrow</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">app/gallery/lightbox/lightbox.gallery.component.html</context>
|
||||
<context context-type="linenumber">64</context>
|
||||
<context context-type="linenumber">72</context>
|
||||
</context-group>
|
||||
<target>key: right arrow</target>
|
||||
</trans-unit>
|
||||
@ -607,6 +607,10 @@
|
||||
<context context-type="sourcefile">app/settings/thumbnail/thumbanil.settings.component.html</context>
|
||||
<context context-type="linenumber">104</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">app/settings/video/video.settings.component.html</context>
|
||||
<context context-type="linenumber">28</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">app/settings/search/search.settings.component.html</context>
|
||||
<context context-type="linenumber">73</context>
|
||||
@ -640,6 +644,10 @@
|
||||
<context context-type="sourcefile">app/settings/thumbnail/thumbanil.settings.component.html</context>
|
||||
<context context-type="linenumber">107</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">app/settings/video/video.settings.component.html</context>
|
||||
<context context-type="linenumber">31</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">app/settings/search/search.settings.component.html</context>
|
||||
<context context-type="linenumber">76</context>
|
||||
@ -796,6 +804,22 @@
|
||||
</context-group>
|
||||
<target>';' separated integers. If size is 200, that thumbnail will have 200^2 pixels.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="b5398623f87ee72ed23f5023918db1707771e925" datatype="html">
|
||||
<source>Video settings</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">app/settings/video/video.settings.component.html</context>
|
||||
<context context-type="linenumber">4</context>
|
||||
</context-group>
|
||||
<target>Video settings</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="6b8862cecf0fd1c8fc1b503e131bfa230d851343" datatype="html">
|
||||
<source>Video support uses ffmpeg. ffmpeg and ffprobe binaries need to be available in the PATH or the @ffmpeg-installer/ffmpeg and @ffprobe-installer/ffprobe optional node packages need to be installed.</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">app/settings/video/video.settings.component.html</context>
|
||||
<context context-type="linenumber">23</context>
|
||||
</context-group>
|
||||
<target>Video support uses ffmpeg. ffmpeg and ffprobe binaries need to be available in the PATH or the @ffmpeg-installer/ffmpeg and @ffprobe-installer/ffprobe optional node packages need to be installed.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="2e75ae3885931555902da6b288ed616843d5dc3c" datatype="html">
|
||||
<source>Search settings</source>
|
||||
<context-group purpose="location">
|
||||
@ -1467,8 +1491,8 @@
|
||||
</context-group>
|
||||
<target>High</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="03d4d456b5f14c7bdd428393e17c724cd5210852" datatype="html">
|
||||
<source> settings saved</source>
|
||||
<trans-unit id="04e4b67fdc5f633a81e0ab32c1751ab20e6e3034" datatype="html">
|
||||
<source>settings saved</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">frontend/app/settings/_abstract/abstract.settings.component.ts</context>
|
||||
<context context-type="linenumber">1</context>
|
||||
@ -1591,13 +1615,13 @@
|
||||
</context-group>
|
||||
<target>Other</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="59b428a89fc1e287f2fb60806ed5f0588cb9c270" datatype="html">
|
||||
<source>Random Photo</source>
|
||||
<trans-unit id="e636143d733fa6a21fa62ffdff2fd76c221e6cac" datatype="html">
|
||||
<source>Random Media</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">frontend/app/settings/random-photo/random-photo.settings.component.ts</context>
|
||||
<context context-type="linenumber">1</context>
|
||||
</context-group>
|
||||
<target>Random Photo</target>
|
||||
<target>Random Media</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="45dda89cf029b7d7b457a8dff01dc4b9a6485816" datatype="html">
|
||||
<source>Thumbnail</source>
|
||||
@ -1639,6 +1663,14 @@
|
||||
</context-group>
|
||||
<target>Password protection disabled</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="2d1ea268a6a9f483dbc2cbfe19bf4256a57a6af4" datatype="html">
|
||||
<source>Video</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">frontend/app/settings/video/video.settings.component.ts</context>
|
||||
<context context-type="linenumber">1</context>
|
||||
</context-group>
|
||||
<target>Video</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
@ -104,7 +104,7 @@
|
||||
<source>download</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">app/gallery/lightbox/lightbox.gallery.component.html</context>
|
||||
<context context-type="linenumber">25</context>
|
||||
<context context-type="linenumber">27</context>
|
||||
</context-group>
|
||||
<target>letöltés</target>
|
||||
</trans-unit>
|
||||
@ -112,7 +112,7 @@
|
||||
<source>info</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">app/gallery/lightbox/lightbox.gallery.component.html</context>
|
||||
<context context-type="linenumber">29</context>
|
||||
<context context-type="linenumber">31</context>
|
||||
</context-group>
|
||||
<target>info</target>
|
||||
</trans-unit>
|
||||
@ -120,11 +120,11 @@
|
||||
<source>toggle fullscreen</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">app/gallery/lightbox/lightbox.gallery.component.html</context>
|
||||
<context context-type="linenumber">36</context>
|
||||
<context context-type="linenumber">38</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">app/gallery/lightbox/lightbox.gallery.component.html</context>
|
||||
<context context-type="linenumber">45</context>
|
||||
<context context-type="linenumber">47</context>
|
||||
</context-group>
|
||||
<target>teljes képernyőre váltás</target>
|
||||
</trans-unit>
|
||||
@ -132,7 +132,7 @@
|
||||
<source>close</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">app/gallery/lightbox/lightbox.gallery.component.html</context>
|
||||
<context context-type="linenumber">52</context>
|
||||
<context context-type="linenumber">54</context>
|
||||
</context-group>
|
||||
<target>bezárás</target>
|
||||
</trans-unit>
|
||||
@ -140,7 +140,7 @@
|
||||
<source>key: left arrow</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">app/gallery/lightbox/lightbox.gallery.component.html</context>
|
||||
<context context-type="linenumber">60</context>
|
||||
<context context-type="linenumber">68</context>
|
||||
</context-group>
|
||||
<target>billentyű: balra nyíl</target>
|
||||
</trans-unit>
|
||||
@ -148,7 +148,7 @@
|
||||
<source>key: right arrow</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">app/gallery/lightbox/lightbox.gallery.component.html</context>
|
||||
<context context-type="linenumber">64</context>
|
||||
<context context-type="linenumber">72</context>
|
||||
</context-group>
|
||||
<target>billentyű: jobbra nyíl</target>
|
||||
</trans-unit>
|
||||
@ -607,6 +607,10 @@
|
||||
<context context-type="sourcefile">app/settings/thumbnail/thumbanil.settings.component.html</context>
|
||||
<context context-type="linenumber">104</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">app/settings/video/video.settings.component.html</context>
|
||||
<context context-type="linenumber">28</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">app/settings/search/search.settings.component.html</context>
|
||||
<context context-type="linenumber">73</context>
|
||||
@ -640,6 +644,10 @@
|
||||
<context context-type="sourcefile">app/settings/thumbnail/thumbanil.settings.component.html</context>
|
||||
<context context-type="linenumber">107</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">app/settings/video/video.settings.component.html</context>
|
||||
<context context-type="linenumber">31</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">app/settings/search/search.settings.component.html</context>
|
||||
<context context-type="linenumber">76</context>
|
||||
@ -796,6 +804,22 @@
|
||||
</context-group>
|
||||
<target>';' elválasztott egész számok. Ha a méretnek pl. 200-t állítasz be, akkor a thumbnail 200^2 pixelből fog állni.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="b5398623f87ee72ed23f5023918db1707771e925" datatype="html">
|
||||
<source>Video settings</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">app/settings/video/video.settings.component.html</context>
|
||||
<context context-type="linenumber">4</context>
|
||||
</context-group>
|
||||
<target>Videó beállítások</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="6b8862cecf0fd1c8fc1b503e131bfa230d851343" datatype="html">
|
||||
<source>Video support uses ffmpeg. ffmpeg and ffprobe binaries need to be available in the PATH or the @ffmpeg-installer/ffmpeg and @ffprobe-installer/ffprobe optional node packages need to be installed.</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">app/settings/video/video.settings.component.html</context>
|
||||
<context context-type="linenumber">23</context>
|
||||
</context-group>
|
||||
<target>A videó lejátszához az ffmpeg szükséges. Az ffmpeg és az ffprobe binárisoknak rendelkezésre kell állniuk a PATH-ban vagy az @ffmpeg-installer/ffmpeg és @ffprobe-installer/ffprobe opcionális node csomagokat kell telepíteni.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="2e75ae3885931555902da6b288ed616843d5dc3c" datatype="html">
|
||||
<source>Search settings</source>
|
||||
<context-group purpose="location">
|
||||
@ -1467,8 +1491,8 @@
|
||||
</context-group>
|
||||
<target>Magas</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="03d4d456b5f14c7bdd428393e17c724cd5210852" datatype="html">
|
||||
<source> settings saved</source>
|
||||
<trans-unit id="04e4b67fdc5f633a81e0ab32c1751ab20e6e3034" datatype="html">
|
||||
<source>settings saved</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">frontend/app/settings/_abstract/abstract.settings.component.ts</context>
|
||||
<context context-type="linenumber">1</context>
|
||||
@ -1591,13 +1615,13 @@
|
||||
</context-group>
|
||||
<target>Egyéb</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="59b428a89fc1e287f2fb60806ed5f0588cb9c270" datatype="html">
|
||||
<source>Random Photo</source>
|
||||
<trans-unit id="e636143d733fa6a21fa62ffdff2fd76c221e6cac" datatype="html">
|
||||
<source>Random Media</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">frontend/app/settings/random-photo/random-photo.settings.component.ts</context>
|
||||
<context context-type="linenumber">1</context>
|
||||
</context-group>
|
||||
<target>Véletlen fotó</target>
|
||||
<target>Véletlenszerű média</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="45dda89cf029b7d7b457a8dff01dc4b9a6485816" datatype="html">
|
||||
<source>Thumbnail</source>
|
||||
@ -1639,6 +1663,14 @@
|
||||
</context-group>
|
||||
<target>Jelszavas védelem tiltva</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="2d1ea268a6a9f483dbc2cbfe19bf4256a57a6af4" datatype="html">
|
||||
<source>Video</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">frontend/app/settings/video/video.settings.component.ts</context>
|
||||
<context context-type="linenumber">1</context>
|
||||
</context-group>
|
||||
<target>Videó</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
||||
|
@ -119,9 +119,11 @@
|
||||
"natives": "1.1.3"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"mysql": "2.16.0",
|
||||
"@ffmpeg-installer/ffmpeg": "1.0.16",
|
||||
"@ffprobe-installer/ffprobe": "1.0.9",
|
||||
"bcrypt": "3.0.2",
|
||||
"gm": "1.23.1",
|
||||
"mysql": "2.16.0",
|
||||
"sharp": "0.21.0"
|
||||
},
|
||||
"engines": {
|
||||
|
Loading…
x
Reference in New Issue
Block a user