livephoto: transcode Apple for HEVC (fix #234)
parent
8adedd1885
commit
f5cfa095ce
|
@ -124,7 +124,7 @@ class VideoController extends ApiBase
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check data was received
|
// Check data was received
|
||||||
if ($returnCode !== 200) {
|
if (200 !== $returnCode) {
|
||||||
return new JSONResponse(['message' => 'Transcode failed'], Http::STATUS_INTERNAL_SERVER_ERROR);
|
return new JSONResponse(['message' => 'Transcode failed'], Http::STATUS_INTERNAL_SERVER_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,6 +210,15 @@ class VideoController extends ApiBase
|
||||||
$name = $liveFile->getName();
|
$name = $liveFile->getName();
|
||||||
$blob = $liveFile->getContent();
|
$blob = $liveFile->getContent();
|
||||||
$mime = $liveFile->getMimeType();
|
$mime = $liveFile->getMimeType();
|
||||||
|
|
||||||
|
if ($this->request->getParam('transcode') && !$this->config->getSystemValue('memories.no_transcode', true)) {
|
||||||
|
// Only Apple uses HEVC for now, so pass this to the transcoder
|
||||||
|
// If this is H.264 it won't get transcoded anyway
|
||||||
|
$liveVideoPath = $liveFile->getStorage()->getLocalFile($liveFile->getInternalPath());
|
||||||
|
if ($this->getUpstream('livephoto', $liveVideoPath, 'max.mp4')) {
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,20 +251,28 @@ class VideoController extends ApiBase
|
||||||
|
|
||||||
// Stream the response to the browser without reading it into memory
|
// Stream the response to the browser without reading it into memory
|
||||||
$headersWritten = false;
|
$headersWritten = false;
|
||||||
curl_setopt($ch, CURLOPT_WRITEFUNCTION, function($curl, $data) use (&$headersWritten) {
|
curl_setopt($ch, CURLOPT_WRITEFUNCTION, function ($curl, $data) use (&$headersWritten, $profile) {
|
||||||
$returnCode = (int) curl_getinfo($curl, CURLINFO_HTTP_CODE);
|
$returnCode = (int) curl_getinfo($curl, CURLINFO_HTTP_CODE);
|
||||||
|
|
||||||
if ($returnCode === 200) {
|
if (200 === $returnCode) {
|
||||||
// Write headers if just got the first chunk of data
|
// Write headers if just got the first chunk of data
|
||||||
if (!$headersWritten) {
|
if (!$headersWritten) {
|
||||||
$headersWritten = true;
|
$headersWritten = true;
|
||||||
$contentType = curl_getinfo($curl, CURLINFO_CONTENT_TYPE);
|
$contentType = curl_getinfo($curl, CURLINFO_CONTENT_TYPE);
|
||||||
header("Content-Type: {$contentType}");
|
header("Content-Type: {$contentType}");
|
||||||
header('Cache-Control: no-cache, no-store, must-revalidate');
|
|
||||||
|
if (str_ends_with($profile, 'mp4')) {
|
||||||
|
// cache full video 24 hours
|
||||||
|
header('Cache-Control: max-age=86400, public');
|
||||||
|
} else {
|
||||||
|
// no caching of segments
|
||||||
|
header('Cache-Control: no-cache, no-store, must-revalidate');
|
||||||
|
}
|
||||||
|
|
||||||
http_response_code($returnCode);
|
http_response_code($returnCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
print($data);
|
echo $data;
|
||||||
ob_flush();
|
ob_flush();
|
||||||
flush();
|
flush();
|
||||||
|
|
||||||
|
@ -264,7 +281,7 @@ class VideoController extends ApiBase
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return strlen($data);
|
return \strlen($data);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Start the request
|
// Start the request
|
||||||
|
|
|
@ -20,7 +20,7 @@ mv "exiftool-$exifver" exiftool
|
||||||
rm -rf *.zip exiftool/t exiftool/html
|
rm -rf *.zip exiftool/t exiftool/html
|
||||||
chmod 755 exiftool/exiftool
|
chmod 755 exiftool/exiftool
|
||||||
|
|
||||||
govod="0.0.18"
|
govod="0.0.19"
|
||||||
echo "Getting go-vod $govod"
|
echo "Getting go-vod $govod"
|
||||||
wget -q "https://github.com/pulsejet/go-vod/releases/download/$govod/go-vod-amd64"
|
wget -q "https://github.com/pulsejet/go-vod/releases/download/$govod/go-vod-amd64"
|
||||||
wget -q "https://github.com/pulsejet/go-vod/releases/download/$govod/go-vod-aarch64"
|
wget -q "https://github.com/pulsejet/go-vod/releases/download/$govod/go-vod-aarch64"
|
||||||
|
|
|
@ -31,7 +31,7 @@ class LivePhotoContentSetup {
|
||||||
video.autoplay = false;
|
video.autoplay = false;
|
||||||
video.playsInline = true;
|
video.playsInline = true;
|
||||||
video.preload = "none";
|
video.preload = "none";
|
||||||
video.src = utils.getLivePhotoVideoUrl(photo);
|
video.src = utils.getLivePhotoVideoUrl(photo, true);
|
||||||
|
|
||||||
const div = document.createElement("div");
|
const div = document.createElement("div");
|
||||||
div.className = "memories-livephoto";
|
div.className = "memories-livephoto";
|
||||||
|
|
|
@ -874,7 +874,7 @@ export default class Viewer extends Mixins(GlobalMixin) {
|
||||||
private async downloadCurrentLiveVideo() {
|
private async downloadCurrentLiveVideo() {
|
||||||
const photo = this.currentPhoto;
|
const photo = this.currentPhoto;
|
||||||
if (!photo) return;
|
if (!photo) return;
|
||||||
window.location.href = utils.getLivePhotoVideoUrl(photo);
|
window.location.href = utils.getLivePhotoVideoUrl(photo, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Open the sidebar */
|
/** Open the sidebar */
|
||||||
|
|
|
@ -133,7 +133,7 @@ export default class Photo extends Mixins(GlobalMixin) {
|
||||||
|
|
||||||
get videoUrl() {
|
get videoUrl() {
|
||||||
if (this.data.liveid) {
|
if (this.data.liveid) {
|
||||||
return utils.getLivePhotoVideoUrl(this.data);
|
return utils.getLivePhotoVideoUrl(this.data, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -240,10 +240,12 @@ export function getFolderRoutePath(basePath: string) {
|
||||||
/**
|
/**
|
||||||
* Get URL to live photo video part
|
* Get URL to live photo video part
|
||||||
*/
|
*/
|
||||||
export function getLivePhotoVideoUrl(p: IPhoto) {
|
export function getLivePhotoVideoUrl(p: IPhoto, transcode: boolean) {
|
||||||
return generateUrl(
|
let url = generateUrl(
|
||||||
`/apps/memories/api/video/livephoto/${p.fileid}?etag=${p.etag}&liveid=${p.liveid}`
|
`/apps/memories/api/video/livephoto/${p.fileid}?etag=${p.etag}&liveid=${p.liveid}`
|
||||||
);
|
);
|
||||||
|
if (transcode) url += "&transcode=1";
|
||||||
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -204,7 +204,7 @@ export async function* deletePhotos(photos: IPhoto[]) {
|
||||||
photos
|
photos
|
||||||
.filter((p) => p.liveid && !p.liveid.startsWith("self__"))
|
.filter((p) => p.liveid && !p.liveid.startsWith("self__"))
|
||||||
.map(async (p) => {
|
.map(async (p) => {
|
||||||
const url = utils.getLivePhotoVideoUrl(p) + "&format=json";
|
const url = utils.getLivePhotoVideoUrl(p, false) + "&format=json";
|
||||||
try {
|
try {
|
||||||
const response = await axios.get(url);
|
const response = await axios.get(url);
|
||||||
const data = response.data;
|
const data = response.data;
|
||||||
|
|
Loading…
Reference in New Issue