1
0
mirror of https://github.com/xuthus83/pigallery2.git synced 2025-01-14 14:43:17 +08:00

improving video support (adding partial ogg,ogv,webm support)

This commit is contained in:
Patrik J. Braun 2018-11-25 15:22:07 +01:00
parent 8ef3d7d0b6
commit f1619ad984
8 changed files with 61 additions and 25 deletions

View File

@ -138,7 +138,8 @@ apt-get install build-essential libkrb5-dev gcc g++
* Random photo url * Random photo url
* You can generate an url that returns a random photo from your gallery. You can use this feature to develop 3rd party applications, like: changing desktop background * You can generate an url that returns a random photo from your gallery. You can use this feature to develop 3rd party applications, like: changing desktop background
* video support * video support
* uses ffmpeg and ffprobe to generate video thumbnails * fully supports *.mp4 files and partially (might have errors with safari and IE) supports *.ogg, *.ogv, *.webm files
* uses ffmpeg and ffprobe to generate video thumbnails
* **Markdown based blogging support** - `future plan` * **Markdown based blogging support** - `future plan`
* you can write some note in the blog.md for every directory * you can write some note in the blog.md for every directory
* bug free :) - `In progress` * bug free :) - `In progress`

View File

@ -35,7 +35,10 @@ export class DiskMangerWorker {
private static isVideo(fullPath: string) { private static isVideo(fullPath: string) {
const extensions = [ const extensions = [
'.mp4' '.mp4',
'.webm',
'.ogv',
'.ogg'
]; ];
const extension = path.extname(fullPath).toLowerCase(); const extension = path.extname(fullPath).toLowerCase();
@ -112,8 +115,8 @@ export class DiskMangerWorker {
return new Promise<VideoMetadata>((resolve, reject) => { return new Promise<VideoMetadata>((resolve, reject) => {
const metadata: VideoMetadata = <VideoMetadata>{ const metadata: VideoMetadata = <VideoMetadata>{
size: { size: {
width: 0, width: 1,
height: 0 height: 1
}, },
bitRate: 0, bitRate: 0,
duration: 0, duration: 0,
@ -135,15 +138,18 @@ export class DiskMangerWorker {
} }
try { try {
for (let i = 0; i < data.streams.length; i++) {
if (data.streams[i].width) {
metadata.size.width = data.streams[i].width;
metadata.size.height = data.streams[i].height;
metadata.size = { metadata.duration = Math.floor(data.streams[i].duration * 1000);
width: data.streams[0].width, metadata.bitRate = parseInt(data.streams[i].bit_rate, 10) || null;
height: data.streams[0].height metadata.creationDate = Date.parse(data.streams[i].tags.creation_time);
}; break;
}
}
metadata.duration = Math.floor(data.streams[0].duration * 1000);
metadata.bitRate = data.streams[0].bit_rate;
metadata.creationDate = Date.parse(data.streams[0].tags.creation_time);
} catch (err) { } catch (err) {
} }
@ -177,7 +183,7 @@ export class DiskMangerWorker {
try { try {
const exif = ExifParserFactory.create(data).parse(); const exif = ExifParserFactory.create(data).parse();
metadata.cameraData = <CameraMetadata> { metadata.cameraData = <CameraMetadata>{
ISO: exif.tags.ISO, ISO: exif.tags.ISO,
model: exif.tags.Model, model: exif.tags.Model,
make: exif.tags.Make, make: exif.tags.Make,
@ -188,7 +194,7 @@ export class DiskMangerWorker {
}; };
if (!isNaN(exif.tags.GPSLatitude) || exif.tags.GPSLongitude || exif.tags.GPSAltitude) { if (!isNaN(exif.tags.GPSLatitude) || exif.tags.GPSLongitude || exif.tags.GPSAltitude) {
metadata.positionData = metadata.positionData || {}; metadata.positionData = metadata.positionData || {};
metadata.positionData.GPSData = <GPSMetadata> { metadata.positionData.GPSData = <GPSMetadata>{
latitude: exif.tags.GPSLatitude, latitude: exif.tags.GPSLatitude,
longitude: exif.tags.GPSLongitude, longitude: exif.tags.GPSLongitude,
altitude: exif.tags.GPSAltitude altitude: exif.tags.GPSAltitude
@ -205,15 +211,15 @@ export class DiskMangerWorker {
if (exif.imageSize) { if (exif.imageSize) {
metadata.size = <MediaDimension> {width: exif.imageSize.width, height: exif.imageSize.height}; metadata.size = <MediaDimension>{width: exif.imageSize.width, height: exif.imageSize.height};
} else if (exif.tags.RelatedImageWidth && exif.tags.RelatedImageHeight) { } else if (exif.tags.RelatedImageWidth && exif.tags.RelatedImageHeight) {
metadata.size = <MediaDimension> {width: exif.tags.RelatedImageWidth, height: exif.tags.RelatedImageHeight}; metadata.size = <MediaDimension>{width: exif.tags.RelatedImageWidth, height: exif.tags.RelatedImageHeight};
} else { } else {
metadata.size = <MediaDimension> {width: 1, height: 1}; metadata.size = <MediaDimension>{width: 1, height: 1};
} }
} catch (err) { } catch (err) {
Logger.debug(LOG_TAG, 'Error parsing exif', fullPath, err); Logger.debug(LOG_TAG, 'Error parsing exif', fullPath, err);
metadata.size = <MediaDimension> {width: 1, height: 1}; metadata.size = <MediaDimension>{width: 1, height: 1};
} }
try { try {
@ -224,8 +230,8 @@ export class DiskMangerWorker {
metadata.positionData.state = iptcData.province_or_state; metadata.positionData.state = iptcData.province_or_state;
metadata.positionData.city = iptcData.city; metadata.positionData.city = iptcData.city;
} }
metadata.keywords = <string[]> (iptcData.keywords || []); metadata.keywords = <string[]>(iptcData.keywords || []);
metadata.creationDate = <number> (iptcData.date_time ? iptcData.date_time.getTime() : metadata.creationDate); metadata.creationDate = <number>(iptcData.date_time ? iptcData.date_time.getTime() : metadata.creationDate);
} catch (err) { } catch (err) {
// Logger.debug(LOG_TAG, "Error parsing iptc data", fullPath, err); // Logger.debug(LOG_TAG, "Error parsing iptc data", fullPath, err);

View File

@ -62,7 +62,20 @@ export class VideoRendererFactory {
if (!!err || data === null) { if (!!err || data === null) {
return reject(err.toString()); return reject(err.toString());
} }
const ratio = data.streams[0].height / data.streams[0].width; /// console.log(data);
let width = null;
let height = null;
for (let i = 0; i < data.streams.length; i++) {
if (data.streams[i].width) {
width = data.streams[i].width;
height = data.streams[i].height;
break;
}
}
if (!width || !height) {
return reject('Can not read video dimension');
}
const ratio = height / width;
const command: FfmpegCommand = ffmpeg(input.mediaPath); const command: FfmpegCommand = ffmpeg(input.mediaPath);
const fileName = path.basename(input.thPath); const fileName = path.basename(input.thPath);
const folder = path.dirname(input.thPath); const folder = path.dirname(input.thPath);

View File

@ -43,7 +43,7 @@ export class GalleryRouter {
} }
private static addGetVideo(app) { private static addGetVideo(app) {
app.get(['/api/gallery/content/:mediaPath(*\.(mp4))'], app.get(['/api/gallery/content/:mediaPath(*\.(mp4|ogg|ogv|webm))'],
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
// TODO: authorize path // TODO: authorize path
GalleryMWs.loadMedia, GalleryMWs.loadMedia,
@ -73,7 +73,7 @@ export class GalleryRouter {
} }
private static addGetVideoThumbnail(app) { private static addGetVideoThumbnail(app) {
app.get('/api/gallery/content/:mediaPath(*\.(mp4))/thumbnail/:size?', app.get('/api/gallery/content/:mediaPath(*\.(mp4|ogg|ogv|webm))/thumbnail/:size?',
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
// TODO: authorize path // TODO: authorize path
GalleryMWs.loadMedia, GalleryMWs.loadMedia,

View File

@ -12,6 +12,10 @@ export class MediaIcon {
} }
getExtension(): string {
return this.media.name.substr(this.media.name.lastIndexOf('.') + 1);
}
iconLoaded() { iconLoaded() {
this.media.readyIcon = true; this.media.readyIcon = true;
} }

View File

@ -21,7 +21,7 @@
</div> </div>
</div> </div>
<div class="row"> <div class="row" *ngIf="media.metadata.creationDate">
<div class="col-2"> <div class="col-2">
<span class="details-icon oi oi-calendar"></span> <span class="details-icon oi oi-calendar"></span>
</div> </div>
@ -36,7 +36,7 @@
</div> </div>
<div class="row" *ngIf="VideoData"> <div class="row" *ngIf="VideoData && (VideoData.duration || VideoData.bitRate)">
<div class="col-2"> <div class="col-2">
<span class="details-icon oi oi-video"></span> <span class="details-icon oi oi-video"></span>
</div> </div>

View File

@ -19,7 +19,7 @@
autoplay autoplay
(error)="onImageError()" (error)="onImageError()"
(timeupdate)="onVideoProgress()" > (timeupdate)="onVideoProgress()" >
<source [src]="gridMedia.getPhotoPath()" type="video/mp4"> <source [src]="gridMedia.getPhotoPath()" type="{{getVideoType()}}">
</video> </video>
</div> </div>

View File

@ -119,6 +119,18 @@ export class GalleryLightboxMediaComponent implements OnChanges {
return this.video.nativeElement.paused; return this.video.nativeElement.paused;
} }
public getVideoType(): string {
switch (this.gridMedia.getExtension().toLowerCase()) {
case 'webm':
return 'video/webm';
case 'ogv':
case 'ogg':
return 'video/ogg';
default:
return 'video/mp4';
}
}
onImageError() { onImageError() {
// TODO:handle error // TODO:handle error
this.imageLoadFinished = true; this.imageLoadFinished = true;