GoogleVideo: fix contentUrl
and add more metadata (#1659)
* GoogleVideo: add more metadata * GoogleVideo: fix `contentUrl` `contentUrl` needs to be the url of the video file itself, not the page or some redirect. Copied the way the url is generated in the RSS code.
This commit is contained in:
parent
86d311f45d
commit
2a83c7d8ec
2 changed files with 75 additions and 5 deletions
|
@ -363,7 +363,7 @@ async function getHtml(ctx) {
|
|||
|
||||
if (claim) {
|
||||
const ogMetadata = await buildClaimOgMetadata(claimUri, claim);
|
||||
const googleVideoMetadata = buildGoogleVideoMetadata(claimUri, claim);
|
||||
const googleVideoMetadata = await buildGoogleVideoMetadata(claimUri, claim);
|
||||
return insertToHead(html, ogMetadata.concat('\n', googleVideoMetadata));
|
||||
}
|
||||
|
||||
|
@ -387,7 +387,7 @@ async function getHtml(ctx) {
|
|||
|
||||
if (claim) {
|
||||
const ogMetadata = await buildClaimOgMetadata(claimUri, claim, {}, referrerQuery);
|
||||
const googleVideoMetadata = buildGoogleVideoMetadata(claimUri, claim);
|
||||
const googleVideoMetadata = await buildGoogleVideoMetadata(claimUri, claim);
|
||||
return insertToHead(html, ogMetadata.concat('\n', googleVideoMetadata));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,22 @@
|
|||
const Mime = require('mime-types');
|
||||
const moment = require('moment');
|
||||
const removeMd = require('remove-markdown');
|
||||
|
||||
// TODO: fix relative path for server
|
||||
const { fetchStreamUrl } = require('../fetchStreamUrl');
|
||||
const { parseURI } = require('../lbryURI');
|
||||
const { OG_IMAGE_URL, SITE_NAME, URL } = require('../../../config.js');
|
||||
const { generateDirectUrl, generateEmbedUrl, getThumbnailCdnUrl, escapeHtmlProperty } = require('../../../ui/util/web');
|
||||
const { generateEmbedUrl, getThumbnailCdnUrl, escapeHtmlProperty } = require('../../../ui/util/web');
|
||||
|
||||
// ****************************************************************************
|
||||
// Utils
|
||||
// ****************************************************************************
|
||||
|
||||
function lbryToOdyseeUrl(claim) {
|
||||
if (claim.canonical_url) {
|
||||
return `${URL}/${claim.canonical_url.replace('lbry://', '').replace(/#/g, ':')}`;
|
||||
}
|
||||
}
|
||||
|
||||
function truncateDescription(description, maxChars = 200) {
|
||||
// Get list of single-codepoint strings
|
||||
|
@ -15,11 +27,57 @@ function truncateDescription(description, maxChars = 200) {
|
|||
return chars.length > maxChars ? truncated + '...' : truncated;
|
||||
}
|
||||
|
||||
// ****************************************************************************
|
||||
// ****************************************************************************
|
||||
|
||||
const Generate = {
|
||||
author: (claim) => {
|
||||
const channelName = claim?.signing_channel?.value?.title || claim?.signing_channel?.name;
|
||||
const channelUrl = lbryToOdyseeUrl(claim.signing_channel);
|
||||
if (channelName && channelUrl) {
|
||||
return { '@type': 'Person', name: channelName, url: channelUrl };
|
||||
}
|
||||
},
|
||||
|
||||
height: (claim) => {
|
||||
return claim?.value?.video?.height;
|
||||
},
|
||||
|
||||
keywords: (claim) => {
|
||||
const tags = claim?.value?.tags;
|
||||
if (tags) {
|
||||
// Some claims, probably created from cli, have a crazy amount of tags.
|
||||
// Limit that to 10.
|
||||
return tags.slice(0, 10).join(',');
|
||||
}
|
||||
},
|
||||
|
||||
potentialAction: (claim) => {
|
||||
// https://developers.google.com/search/docs/advanced/structured-data/video?hl=en#seek
|
||||
if ((claim?.value?.video || claim?.value?.audio) && claim.canonical_url) {
|
||||
return {
|
||||
'@type': 'SeekToAction',
|
||||
target: `${lbryToOdyseeUrl(claim)}?t={seek_to_second_number}`,
|
||||
'startOffset-input': 'required name=seek_to_second_number',
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
thumbnail: (url) => {
|
||||
// We don't have 'width' and 'height' from the claim :(
|
||||
return { '@type': 'ImageObject', url };
|
||||
},
|
||||
|
||||
width: (claim) => {
|
||||
return claim?.value?.video?.width;
|
||||
},
|
||||
};
|
||||
|
||||
// ****************************************************************************
|
||||
// buildGoogleVideoMetadata
|
||||
// ****************************************************************************
|
||||
|
||||
function buildGoogleVideoMetadata(uri, claim) {
|
||||
async function buildGoogleVideoMetadata(uri, claim) {
|
||||
const { claimName } = parseURI(uri);
|
||||
const { meta, value } = claim;
|
||||
const media = value && value.video;
|
||||
|
@ -41,6 +99,10 @@ function buildGoogleVideoMetadata(uri, claim) {
|
|||
|
||||
const claimThumbnail = escapeHtmlProperty(thumbnail) || getThumbnailCdnUrl(OG_IMAGE_URL) || `${URL}/public/v2-og.png`;
|
||||
|
||||
const fileExt = value.source && value.source.media_type && '.' + Mime.extension(value.source.media_type);
|
||||
const claimStreamUrl =
|
||||
(await fetchStreamUrl(claim.name, claim.claim_id)).replace('/v4/', '/v3/') + (fileExt || '.mp4'); // v3 = mp4 always, v4 may redirect to m3u8;
|
||||
|
||||
// https://developers.google.com/search/docs/data-types/video
|
||||
const googleVideoMetadata = {
|
||||
// --- Must ---
|
||||
|
@ -52,8 +114,16 @@ function buildGoogleVideoMetadata(uri, claim) {
|
|||
uploadDate: `${new Date(releaseTime * 1000).toISOString()}`,
|
||||
// --- Recommended ---
|
||||
duration: mediaDuration ? moment.duration(mediaDuration * 1000).toISOString() : undefined,
|
||||
contentUrl: generateDirectUrl(claim.name, claim.claim_id),
|
||||
url: lbryToOdyseeUrl(claim),
|
||||
contentUrl: claimStreamUrl,
|
||||
embedUrl: generateEmbedUrl(claim.name, claim.claim_id),
|
||||
// --- Misc ---
|
||||
author: Generate.author(claim),
|
||||
thumbnail: Generate.thumbnail(claimThumbnail),
|
||||
keywords: Generate.keywords(claim),
|
||||
width: Generate.width(claim),
|
||||
height: Generate.height(claim),
|
||||
potentialAction: Generate.potentialAction(claim),
|
||||
};
|
||||
|
||||
if (
|
||||
|
|
Loading…
Reference in a new issue