lp: support Samsung HEIC

Signed-off-by: Varun Patil <radialapps@gmail.com>
pull/807/merge
Varun Patil 2023-10-04 23:51:52 -07:00
parent 1360f411ca
commit 20d049f160
5 changed files with 25 additions and 9 deletions

View File

@ -16,6 +16,7 @@ All notable changes to this project will be documented in this file.
- **Feature**: Confirmation box on deletion ([#798](https://github.com/pulsejet/memories/issues/798)) - **Feature**: Confirmation box on deletion ([#798](https://github.com/pulsejet/memories/issues/798))
- **Feature**: Prompt on editing metadata if date will be lost - **Feature**: Prompt on editing metadata if date will be lost
- **Feature**: Allow changing binary temp directory ([#821](https://github.com/pulsejet/memories/issues/821)) - **Feature**: Allow changing binary temp directory ([#821](https://github.com/pulsejet/memories/issues/821))
- **Feature**: Support for Samsung HEIC Motion Photos on newer devices
- **Fix**: Support for transcoding MKV files. - **Fix**: Support for transcoding MKV files.
## [v5.4.1] - 2023-08-20 ## [v5.4.1] - 2023-08-20

View File

@ -15,7 +15,7 @@ Nextcloud comes bundled with an official "Photos" app. This page provides a brie
1. **Archive**: Allows separating photos to a different folder quickly. Photos has no equivalent function. 1. **Archive**: Allows separating photos to a different folder quickly. Photos has no equivalent function.
1. **External Folder Sharing**: Allows sharing a folder to non-Nextcloud users. Photos has no equivalent function ([issue](https://github.com/nextcloud/photos/issues/236)). 1. **External Folder Sharing**: Allows sharing a folder to non-Nextcloud users. Photos has no equivalent function ([issue](https://github.com/nextcloud/photos/issues/236)).
1. **EXIF Data Editing**: Memories allows basic editing of EXIF data including fields such as date taken, title, description etc. Photos has no equivalent function. 1. **EXIF Data Editing**: Memories allows basic editing of EXIF data including fields such as date taken, title, description etc. Photos has no equivalent function.
1. **Support for iOS and Google Live Photos**: Memories supports live photos, Photos does not. ([issue](https://github.com/nextcloud/photos/issues/344), [issue](https://github.com/nextcloud/photos/issues/365)) 1. **Support for iOS / Google / Samsung Live Photos**: Memories supports live photos, Photos does not. ([issue](https://github.com/nextcloud/photos/issues/344), [issue](https://github.com/nextcloud/photos/issues/365))
1. **Advanced Multi-Selection**: Memories supports all multi-selection methods including selecting a day, selecting with Shift+Click and with Touch+Drag. Photos does not support these ([issue](https://github.com/nextcloud/photos/issues/1154), [issue](https://github.com/nextcloud/photos/issues/83)) 1. **Advanced Multi-Selection**: Memories supports all multi-selection methods including selecting a day, selecting with Shift+Click and with Touch+Drag. Photos does not support these ([issue](https://github.com/nextcloud/photos/issues/1154), [issue](https://github.com/nextcloud/photos/issues/83))
1. **Viewer Gestures**: Memories provides a superior photo viewer experience, including gestures such as zoom in and out using touch. 1. **Viewer Gestures**: Memories provides a superior photo viewer experience, including gestures such as zoom in and out using touch.
1. **Preview pipelining**: For maximum performance, Memories highly optimizes loading thumbnails, whereas Photos loads them one by one. 1. **Preview pipelining**: For maximum performance, Memories highly optimizes loading thumbnails, whereas Photos loads them one by one.

View File

@ -148,11 +148,18 @@ class VideoController extends GenericApiController
} catch (\Exception $e) { } catch (\Exception $e) {
throw Exceptions::NotFound('file trailer'); throw Exceptions::NotFound('file trailer');
} }
} elseif ('self__embeddedvideo' === $liveid) { } elseif (str_starts_with($liveid, 'self__exifbin=')) {
$field = substr($liveid, \strlen('self__exifbin='));
// Need explicit whitelisting here because this is user input
if (!\in_array($field, ['EmbeddedVideoFile', 'MotionPhotoVideo'], true)) {
throw Exceptions::BadRequest('Invalid binary EXIF field');
}
try { // Get embedded video file try { // Get embedded video file
$blob = Exif::getBinaryExifProp($path, '-EmbeddedVideoFile'); $blob = Exif::getBinaryExifProp($path, "-{$field}");
} catch (\Exception $e) { } catch (\Exception $e) {
throw Exceptions::NotFound('embedded video'); throw Exceptions::NotFound('Could not read binary EXIF field');
} }
} elseif (str_starts_with($liveid, 'self__traileroffset=')) { } elseif (str_starts_with($liveid, 'self__traileroffset=')) {
// Remove prefix // Remove prefix

View File

@ -56,7 +56,7 @@ class LivePhoto
return "self__traileroffset={$videoOffset}"; return "self__traileroffset={$videoOffset}";
} }
// Google JPEG and Samsung HEIC (Apple?) // Google JPEG and Samsung HEIC / JPEG (Apple?)
if (\array_key_exists('MotionPhoto', $exif)) { if (\array_key_exists('MotionPhoto', $exif)) {
if ('image/jpeg' === $exif['MIMEType']) { if ('image/jpeg' === $exif['MIMEType']) {
// Google Motion Photo JPEG // Google Motion Photo JPEG
@ -91,12 +91,20 @@ class LivePhoto
// Fallback: video should hopefully be in trailer // Fallback: video should hopefully be in trailer
return 'self__trailer'; return 'self__trailer';
} }
if ('image/heic' === $exif['MIMEType']) {
// Samsung HEIC -- no way to get this out yet else if ('image/heic' === $exif['MIMEType']) {
return ''; // Samsung HEIC -- no way to get this out yet (DirectoryItemLength is senseless)
// The reason this is above the MotionPhotoVideo check is because extracting binary
// EXIF fields on the fly is extremely expensive compared to trailer extraction.
} }
} }
// Samsung HEIC (at least S21)
if (\array_key_exists('MotionPhotoVideo', $exif) && !empty($exif['MotionPhotoVideo'])) {
// It's a binary exif field, decode when the user requests it
return 'self__exifbin=MotionPhotoVideo';
}
return ''; return '';
} }

View File

@ -12,7 +12,7 @@ class Exif
{ {
private const FORBIDDEN_EDIT_MIMES = ['image/bmp', 'image/x-dcraw', 'video/MP2T']; private const FORBIDDEN_EDIT_MIMES = ['image/bmp', 'image/x-dcraw', 'video/MP2T'];
private const EXIFTOOL_TIMEOUT = 30000; private const EXIFTOOL_TIMEOUT = 30000;
private const EXIFTOOL_ARGS = ['-api', 'QuickTimeUTC=1', '-n', '-json', '--b']; private const EXIFTOOL_ARGS = ['-api', 'QuickTimeUTC=1', '-n', '-json'];
/** Opened instance of exiftool when running in command mode */ /** Opened instance of exiftool when running in command mode */
private static $staticProc; private static $staticProc;