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:
parent
8ef3d7d0b6
commit
f1619ad984
@ -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`
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
@ -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>
|
||||||
|
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user