video: allow transcoding everywhere
parent
874258dae9
commit
e60d97ae5e
|
@ -121,6 +121,9 @@ class PublicController extends AuthPublicShareController
|
||||||
$policy->addAllowedScriptDomain('blob:');
|
$policy->addAllowedScriptDomain('blob:');
|
||||||
$policy->addAllowedMediaDomain('blob:');
|
$policy->addAllowedMediaDomain('blob:');
|
||||||
|
|
||||||
|
// Image editor
|
||||||
|
$policy->addAllowedConnectDomain('data:');
|
||||||
|
|
||||||
// Allow nominatim for metadata
|
// Allow nominatim for metadata
|
||||||
$policy->addAllowedConnectDomain('nominatim.openstreetmap.org');
|
$policy->addAllowedConnectDomain('nominatim.openstreetmap.org');
|
||||||
$policy->addAllowedFrameDomain('www.openstreetmap.org');
|
$policy->addAllowedFrameDomain('www.openstreetmap.org');
|
||||||
|
|
|
@ -34,17 +34,14 @@ class VideoController extends ApiBase
|
||||||
/**
|
/**
|
||||||
* @NoAdminRequired
|
* @NoAdminRequired
|
||||||
*
|
*
|
||||||
|
* @PublicPage
|
||||||
|
*
|
||||||
* @NoCSRFRequired
|
* @NoCSRFRequired
|
||||||
*
|
*
|
||||||
* Transcode a video to HLS by proxy
|
* Transcode a video to HLS by proxy
|
||||||
*/
|
*/
|
||||||
public function transcode(string $client, string $fileid, string $profile): Http\Response
|
public function transcode(string $client, int $fileid, string $profile): Http\Response
|
||||||
{
|
{
|
||||||
$user = $this->userSession->getUser();
|
|
||||||
if (null === $user) {
|
|
||||||
return new JSONResponse([], Http::STATUS_PRECONDITION_FAILED);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure not running in read-only mode
|
// Make sure not running in read-only mode
|
||||||
if (false !== $this->config->getSystemValue('memories.no_transcode', 'UNSET')) {
|
if (false !== $this->config->getSystemValue('memories.no_transcode', 'UNSET')) {
|
||||||
return new JSONResponse(['message' => 'Transcoding disabled'], Http::STATUS_FORBIDDEN);
|
return new JSONResponse(['message' => 'Transcoding disabled'], Http::STATUS_FORBIDDEN);
|
||||||
|
@ -56,11 +53,10 @@ class VideoController extends ApiBase
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get file
|
// Get file
|
||||||
$files = $this->rootFolder->getUserFolder($user->getUID())->getById($fileid);
|
$file = $this->getUserFile($fileid);
|
||||||
if (0 === \count($files)) {
|
if (!$file) {
|
||||||
return new JSONResponse(['message' => 'File not found'], Http::STATUS_NOT_FOUND);
|
return new JSONResponse(['message' => 'File not found'], Http::STATUS_NOT_FOUND);
|
||||||
}
|
}
|
||||||
$file = $files[0];
|
|
||||||
|
|
||||||
if (!($file->getPermissions() & \OCP\Constants::PERMISSION_READ)) {
|
if (!($file->getPermissions() & \OCP\Constants::PERMISSION_READ)) {
|
||||||
return new JSONResponse(['message' => 'File not readable'], Http::STATUS_FORBIDDEN);
|
return new JSONResponse(['message' => 'File not readable'], Http::STATUS_FORBIDDEN);
|
||||||
|
@ -250,7 +246,15 @@ class VideoController extends ApiBase
|
||||||
private function getUpstreamInternal($client, $path, $profile)
|
private function getUpstreamInternal($client, $path, $profile)
|
||||||
{
|
{
|
||||||
$path = rawurlencode($path);
|
$path = rawurlencode($path);
|
||||||
$ch = curl_init("http://127.0.0.1:47788/{$client}{$path}/{$profile}");
|
|
||||||
|
// Make sure query params are repeated
|
||||||
|
// For example, in folder sharing, we need the params on every request
|
||||||
|
$url = "http://127.0.0.1:47788/{$client}{$path}/{$profile}";
|
||||||
|
if ($params = $_SERVER['QUERY_STRING']) {
|
||||||
|
$url .= "?{$params}";
|
||||||
|
}
|
||||||
|
|
||||||
|
$ch = curl_init($url);
|
||||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||||
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
|
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
|
||||||
curl_setopt($ch, CURLOPT_HEADER, 0);
|
curl_setopt($ch, CURLOPT_HEADER, 0);
|
||||||
|
|
|
@ -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.22"
|
govod="0.0.23"
|
||||||
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"
|
||||||
|
|
|
@ -88,9 +88,11 @@ export default class Metadata extends Mixins(GlobalMixin) {
|
||||||
this.nominatim = null;
|
this.nominatim = null;
|
||||||
|
|
||||||
let state = this.state;
|
let state = this.state;
|
||||||
const res = await axios.get<any>(
|
let url = generateUrl("/apps/memories/api/image/info/{id}", {
|
||||||
generateUrl("/apps/memories/api/image/info/{id}", { id: fileInfo.id })
|
id: fileInfo.id,
|
||||||
);
|
});
|
||||||
|
url = utils.addQueryTokensToUrl(url);
|
||||||
|
const res = await axios.get<any>(url);
|
||||||
if (state !== this.state) return;
|
if (state !== this.state) return;
|
||||||
|
|
||||||
this.baseInfo = res.data;
|
this.baseInfo = res.data;
|
||||||
|
|
|
@ -5,6 +5,7 @@ import axios from "@nextcloud/axios";
|
||||||
import { showError } from "@nextcloud/dialogs";
|
import { showError } from "@nextcloud/dialogs";
|
||||||
import { translate as t } from "@nextcloud/l10n";
|
import { translate as t } from "@nextcloud/l10n";
|
||||||
import { getCurrentUser } from "@nextcloud/auth";
|
import { getCurrentUser } from "@nextcloud/auth";
|
||||||
|
import { addQueryTokensToUrl } from "../services/Utils";
|
||||||
|
|
||||||
const config_noTranscode = loadState(
|
const config_noTranscode = loadState(
|
||||||
"memories",
|
"memories",
|
||||||
|
@ -115,12 +116,16 @@ class VideoContentSetup {
|
||||||
}
|
}
|
||||||
|
|
||||||
getHLSsrc(content: any) {
|
getHLSsrc(content: any) {
|
||||||
|
// Get base URL
|
||||||
const fileid = content.data.photo.fileid;
|
const fileid = content.data.photo.fileid;
|
||||||
const baseUrl = generateUrl(
|
let url = generateUrl(
|
||||||
`/apps/memories/api/video/transcode/${videoClientId}/${fileid}`
|
`/apps/memories/api/video/transcode/${videoClientId}/${fileid}/index.m3u8`
|
||||||
);
|
);
|
||||||
|
|
||||||
|
url = addQueryTokensToUrl(url);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
src: `${baseUrl}/index.m3u8`,
|
src: url,
|
||||||
type: "application/x-mpegURL",
|
type: "application/x-mpegURL",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -227,19 +232,18 @@ class VideoContentSetup {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Get correct orientation
|
// Get correct orientation
|
||||||
axios
|
let url = generateUrl("/apps/memories/api/image/info/{id}", {
|
||||||
.get<any>(
|
id: content.data.photo.fileid,
|
||||||
generateUrl("/apps/memories/api/image/info/{id}", {
|
});
|
||||||
id: content.data.photo.fileid,
|
url = addQueryTokensToUrl(url);
|
||||||
})
|
|
||||||
)
|
|
||||||
.then((response) => {
|
|
||||||
content.data.exif = response.data?.exif;
|
|
||||||
|
|
||||||
// Update only after video is ready
|
axios.get<any>(url).then((response) => {
|
||||||
// Otherwise the poster image is rotated
|
content.data.exif = response.data?.exif;
|
||||||
if (canPlay) this.updateRotation(content);
|
|
||||||
});
|
// Update only after video is ready
|
||||||
|
// Otherwise the poster image is rotated
|
||||||
|
if (canPlay) this.updateRotation(content);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
destroyVideo(content: any) {
|
destroyVideo(content: any) {
|
||||||
|
|
|
@ -602,11 +602,6 @@ export default class Timeline extends Mixins(GlobalMixin, UserConfig) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Favorites
|
|
||||||
if (this.$route.name === "folder-share") {
|
|
||||||
query.set("folder_share", this.$route.params.token);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Month view
|
// Month view
|
||||||
if (this.isMonthView) {
|
if (this.isMonthView) {
|
||||||
query.set("monthView", "1");
|
query.set("monthView", "1");
|
||||||
|
@ -614,6 +609,7 @@ export default class Timeline extends Mixins(GlobalMixin, UserConfig) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create query string and append to URL
|
// Create query string and append to URL
|
||||||
|
utils.addQueryTokens(query);
|
||||||
const queryStr = query.toString();
|
const queryStr = query.toString();
|
||||||
if (queryStr) {
|
if (queryStr) {
|
||||||
url += "?" + queryStr;
|
url += "?" + queryStr;
|
||||||
|
|
|
@ -23,6 +23,7 @@ import { generateUrl } from "@nextcloud/router";
|
||||||
import camelcase from "camelcase";
|
import camelcase from "camelcase";
|
||||||
import { IFileInfo, IPhoto } from "../types";
|
import { IFileInfo, IPhoto } from "../types";
|
||||||
import { isNumber } from "./NumberUtils";
|
import { isNumber } from "./NumberUtils";
|
||||||
|
import { addQueryTokens } from "./Utils";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an url encoded path
|
* Get an url encoded path
|
||||||
|
@ -153,9 +154,7 @@ const getPreviewUrl = function (
|
||||||
query.set("a", square ? "0" : "1");
|
query.set("a", square ? "0" : "1");
|
||||||
|
|
||||||
// Public preview
|
// Public preview
|
||||||
if (vuerouter.currentRoute.name === "folder-share") {
|
addQueryTokens(query);
|
||||||
query.set("folder_share", vuerouter.currentRoute.params.token);
|
|
||||||
}
|
|
||||||
|
|
||||||
return url + "?" + query.toString();
|
return url + "?" + query.toString();
|
||||||
};
|
};
|
||||||
|
|
|
@ -237,6 +237,34 @@ export function getFolderRoutePath(basePath: string) {
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add any access tokens to query param if required
|
||||||
|
* @param query Query string
|
||||||
|
*/
|
||||||
|
export function addQueryTokens(query: URLSearchParams) {
|
||||||
|
if (vuerouter.currentRoute.name === "folder-share") {
|
||||||
|
query.set("folder_share", vuerouter.currentRoute.params.token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add query tokens to a string URL
|
||||||
|
* @param url URL to add tokens to
|
||||||
|
*/
|
||||||
|
export function addQueryTokensToUrl(url: string) {
|
||||||
|
const query = new URLSearchParams();
|
||||||
|
addQueryTokens(query);
|
||||||
|
if (query.toString()) {
|
||||||
|
if (url.indexOf("?") === -1) {
|
||||||
|
url += "?";
|
||||||
|
} else {
|
||||||
|
url += "&";
|
||||||
|
}
|
||||||
|
url += query.toString();
|
||||||
|
}
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get URL to live photo video part
|
* Get URL to live photo video part
|
||||||
*/
|
*/
|
||||||
|
@ -254,11 +282,7 @@ export function getLivePhotoVideoUrl(p: IPhoto, transcode: boolean) {
|
||||||
query.set("transcode", videoClientIdPersistent);
|
query.set("transcode", videoClientIdPersistent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add auth token for public share
|
addQueryTokens(query);
|
||||||
if (vuerouter.currentRoute.name === "folder-share") {
|
|
||||||
query.set("folder_share", vuerouter.currentRoute.params.token);
|
|
||||||
}
|
|
||||||
|
|
||||||
return url + "?" + query.toString();
|
return url + "?" + query.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue