WebM Spritesheet/Transcode from canonical config failed in google cloud - google-cloud-transcoder

WebM Spritesheet/Transcode from canonical config failed to complete with error message: Request field config.editList[0].startTimeOffset is 0s, expected start time less than the minimum duration of all inputs for this atom (0s).
The config used is from https://cloud.google.com/transcoder/docs/how-to/generate-spritesheet#generate_image_periodically
Project Number: PROJECT-NUMBER
Job ID: projects/PROJECT-NUMBER/locations/us-central1/jobs/JOB-ID
Location: us-central1
Job Config
{
"name": "projects/PROJECT-NUMBER/locations/us-central1/jobs/JOB-ID",
"config": {
"inputs": [
{
"key": "input0",
"uri": "gs://input_video.webm"
}
],
"editList": [
{
"key": "atom0",
"inputs": [
"input0"
],
"startTimeOffset": "0s"
}
],
"elementaryStreams": [
{
"videoStream": {
"codec": "h264",
"profile": "high",
"preset": "veryfast",
"heightPixels": 360,
"widthPixels": 640,
"pixelFormat": "yuv420p",
"bitrateBps": 550000,
"rateControlMode": "vbr",
"crfLevel": 21,
"vbvSizeBits": 550000,
"vbvFullnessBits": 495000,
"gopDuration": "3s",
"entropyCoder": "cabac",
"frameRate": 60
},
"key": "video-stream0"
},
{
"audioStream": {
"codec": "aac",
"bitrateBps": 64000,
"channelCount": 2,
"channelLayout": [
"fl",
"fr"
],
"sampleRateHertz": 48000
},
"key": "audio-stream0"
}
],
"muxStreams": [
{
"key": "sd",
"fileName": "sd.mp4",
"container": "mp4",
"elementaryStreams": [
"video-stream0",
"audio-stream0"
]
}
],
"output": {
"uri": "gs://output/"
},
"spriteSheets": [
{
"format": "jpeg",
"filePrefix": "small-sprite-sheet",
"spriteWidthPixels": 64,
"spriteHeightPixels": 32,
"startTimeOffset": "0s",
"interval": "7s",
"quality": 100
},
{
"format": "jpeg",
"filePrefix": "large-sprite-sheet",
"spriteWidthPixels": 128,
"spriteHeightPixels": 72,
"startTimeOffset": "0s",
"interval": "7s",
"quality": 100
}
]
},
"state": "FAILED",
"failureReason": "Job validation failed: Request field config.editList[0].startTimeOffset is 0s, expected start time less than the minimum duration of all inputs for this atom (0s).",
"ttlAfterCompletionDays": 30
}

Looks like the duration we're calculated for the input is 0 seconds. So either the input is empty, or we're unable to calculate the duration of the input. Do you know if the former is the case? For the latter, if the customer provides an endTimeOffset in their editList, then we should use that duration, which would get past this validation error.
Totally missed the input link in comment#1, sorry about that! So when I run ffprobe on the input, I get
Metadata:
encoder : Chrome
Duration: N/A, start: 0.000000, bitrate: N/A
Stream #0:0(eng): Audio: opus, 48000 Hz, mono, fltp (default)
Stream #0:1(eng): Video: h264 (Baseline), yuv420p(progressive), 640x480 [SAR 1:1 DAR 4:3], 29.97 fps, 29.97 tbr, 1k tbn, 2k tbc (default)
We do generate the editList, but in this case we couldn't get valid duration from the input. My guess is that this worked previously because the inputs used contained timing metadata, though I could help confirm that if you have the input from a job that went through successfully. I'd suggest specifying the endTimeOffset in the job config if possible (especially if different encoding is used from input-to-input).

Related

The graph api is throwing BadRequest while writing mp4 file

I am trying to write a video file chunk by chunk at onedrive but, the graph api throws me a BadRequest.
Can anyone help me out...
I am using this code to write the files, other than video file I am able to create and write the file at onedrive.
graphClient.Users[UserEmailID].Drive.Items[Item.ParentItemID].Children.Request().AddAsync(SourceDriveItem).Result;
Following is the Json of SourceDriveItem
{
"file": {
"hashes": {
"quickXorHash": "bxXAIfX9S1d5xN8dqthmIc0m5L8=",
"#odata.type": "microsoft.graph.hashes"
},
"mimeType": "video/mp4",
"#odata.type": "microsoft.graph.file"
},
"fileSystemInfo": {
"createdDateTime": "2021-08-20T07:38:52+00:00",
"lastModifiedDateTime": "2021-08-20T07:38:52+00:00",
"#odata.type": "microsoft.graph.fileSystemInfo"
},
"photo": {
"takenDateTime": "2015-08-07T09:13:02+00:00",
"#odata.type": "microsoft.graph.photo"
},
"size": 1570024,
"video": {
"audioBitsPerSample": 110288,
"audioChannels": 2,
"audioFormat": "{00001610-0000-0010-8000-00AA00389B71}",
"audioSamplesPerSecond": 48000,
"bitrate": 291808,
"duration": 30526,
"fourCC": "H264",
"frameRate": 30000.0,
"height": 270,
"width": 480,
"#odata.type": "microsoft.graph.video"
},
"createdDateTime": "2021-08-20T07:38:52+00:00",
"lastModifiedBy": {
"user": {
"displayName": "SysTools Dev2",
"id": "38a682a6-5390-4e43-8610-442f35cb0026",
"#odata.type": "microsoft.graph.identity",
"email": "admin#dev2systoolsgroup.onmicrosoft.com"
},
"#odata.type": "microsoft.graph.identitySet"
},
"lastModifiedDateTime": "2021-08-20T07:38:52+00:00",
"name": "file_example_MP4_480_1_5MG.mp4",
"#odata.type": "microsoft.graph.driveItem"
}
I just set null to the Video property in the request body and it get solved. So avoid setting the Video object in DriveItem while adding the file

Transcoder fails to write output due to permission issue

The transcode job is able to read the file but the output directory is not getting created.
I checked the log and the error is due to permission issue with Storage. I would like to get your help related to this issue.
Logs:
The response of the video transcoding is as follows.
{
"name": "projects/PROJECT-NUMBER/locations/us-central1/jobs/JOB-ID",
"config": {
"inputs": [
{
"key": "input0",
"uri": "gs://input.mp4"
}
],
"editList": [
{
"key": "atom0",
"inputs": [
"input0"
],
"startTimeOffset": "0s"
}
],
"elementaryStreams": [
{
"videoStream": {
"codec": "h264",
"profile": "high",
"preset": "veryfast",
"heightPixels": 720,
"widthPixels": 1280,
"pixelFormat": "yuv420p",
"bitrateBps": 1500000,
"rateControlMode": "vbr",
"crfLevel": 21,
"vbvSizeBits": 1500000,
"vbvFullnessBits": 1350000,
"gopDuration": "3s",
"entropyCoder": "cabac",
"frameRate": 60
},
"key": "video-streamR480P"
},
{
"videoStream": {
"codec": "h264",
"profile": "high",
"preset": "veryfast",
"heightPixels": 1080,
"widthPixels": 1920,
"pixelFormat": "yuv420p",
"bitrateBps": 3000000,
"rateControlMode": "vbr",
"crfLevel": 21,
"vbvSizeBits": 3000000,
"vbvFullnessBits": 2700000,
"gopDuration": "3s",
"entropyCoder": "cabac",
"frameRate": 60
},
"key": "video-streamR720P"
},
{
"videoStream": {
"codec": "h264",
"profile": "high",
"preset": "veryfast",
"heightPixels": 1440,
"widthPixels": 2560,
"pixelFormat": "yuv420p",
"bitrateBps": 6000000,
"rateControlMode": "vbr",
"crfLevel": 21,
"vbvSizeBits": 6000000,
"vbvFullnessBits": 5400000,
"gopDuration": "3s",
"entropyCoder": "cabac",
"frameRate": 60
},
"key": "video-streamR1080P"
},
{
"videoStream": {
"codec": "h264",
"profile": "high",
"preset": "veryfast",
"heightPixels": 2160,
"widthPixels": 3840,
"pixelFormat": "yuv420p",
"bitrateBps": 10000000,
"rateControlMode": "vbr",
"crfLevel": 21,
"vbvSizeBits": 10000000,
"vbvFullnessBits": 9000000,
"gopDuration": "3s",
"entropyCoder": "cabac",
"frameRate": 60
},
"key": "video-streamR1440P"
},
{
"audioStream": {
"codec": "aac",
"bitrateBps": 512000,
"channelCount": 2,
"channelLayout": [
"fl",
"fr"
],
"sampleRateHertz": 48000
},
"key": "audio-stream"
}
],
"muxStreams": [
{
"key": "mux-streamR480P",
"fileName": "mux-streamR480P.m4s",
"container": "fmp4",
"elementaryStreams": [
"video-streamR480P"
]
},
{
"key": "mux-streamR720P",
"fileName": "mux-streamR720P.m4s",
"container": "fmp4",
"elementaryStreams": [
"video-streamR720P"
]
},
{
"key": "mux-streamR1080P",
"fileName": "mux-streamR1080P.m4s",
"container": "fmp4",
"elementaryStreams": [
"video-streamR1080P"
]
},
{
"key": "mux-streamR1440P",
"fileName": "mux-streamR1440P.m4s",
"container": "fmp4",
"elementaryStreams": [
"video-streamR1440P"
]
},
{
"key": "mux-streamaudio-stream",
"fileName": "mux-streamaudio-stream.m4s",
"container": "fmp4",
"elementaryStreams": [
"audio-stream"
]
}
],
"manifests": [
{
"fileName": "manifest.mpd",
"type": "DASH",
"muxStreams": [
"mux-streamR480P",
"mux-streamR720P",
"mux-streamR1080P",
"mux-streamR1440P",
"mux-streamaudio-stream"
]
},
{
"fileName": "master.m3u8",
"type": "HLS",
"muxStreams": [
"mux-streamR480P",
"mux-streamR720P",
"mux-streamR1080P",
"mux-streamR1440P",
"mux-streamaudio-stream"
]
}
],
"output": {
"uri": "gs://output-bucket/"
}
}, "ttlAfterCompletionDays": 30
}
Job_ID is XXXXXXXXXXXXXXXXXXXXXXXX.
Please help.
I have checked the job and found the failure message:
Job validation failed: atom atom0 does not have any inputs (input0) with an audio track
It has nothing to do with storage permission. Can you fix the edit list with an input that includes audio track and try again?
I think the permission error that you observe is happening on the client side and is not related to the Transcoder API

How to retrieve game title bound to video [duplicate]

This question already has answers here:
Youtube API Retrieve Live Stream Game Title
(2 answers)
Closed 1 year ago.
Does anyone know how to get the game title assigned to video via the Youtube API?
Game title screenshot from YT web. Here I need to get the Call of Duty game from this video:
Documentation doesn't have any information regarding game title in the video resource: https://developers.google.com/youtube/v3/docs/videos
API query with the broadest content settings returns this:
{
"kind": "youtube#videoListResponse",
"etag": "0KGf7UH0NGSsvuQJqAEX4e1mE00",
"items": [
{
"kind": "youtube#video",
"etag": "atR4AXswOz04SvjBEFuPTUpgEKo",
"id": "Tn2TgqkrCng",
"snippet": {
"publishedAt": "2016-09-23T16:31:31Z",
"channelId": "UCv2IxyoJetx3b3nPbHJbx3g",
"title": "Batman: The Telltale Games Series [#7][Epizod 2 FINAŁ]",
"description": "Wrzućcie like'a na facebooku: ",
"thumbnails": {
"default": {
"url": "https://i.ytimg.com/vi/Tn2TgqkrCng/default.jpg",
"width": 120,
"height": 90
},
"medium": {
"url": "https://i.ytimg.com/vi/Tn2TgqkrCng/mqdefault.jpg",
"width": 320,
"height": 180
},
"high": {
"url": "https://i.ytimg.com/vi/Tn2TgqkrCng/hqdefault.jpg",
"width": 480,
"height": 360
},
"standard": {
"url": "https://i.ytimg.com/vi/Tn2TgqkrCng/sddefault.jpg",
"width": 640,
"height": 480
},
"maxres": {
"url": "https://i.ytimg.com/vi/Tn2TgqkrCng/maxresdefault.jpg",
"width": 1280,
"height": 720
}
},
"channelTitle": "Tivolt",
"tags": [
"tivolt",
"let's play",
"zagrajmy w",
"gameplay",
"gry",
"zagrajmy",
"vlog",
"fajne",
"gta",
"batman",
"telltale"
],
"categoryId": "20",
"liveBroadcastContent": "none",
"localized": {
"title": "Batman: The Telltale Games Series [#7][Epizod 2 FINAŁ]",
"description": "Wrzućcie like'a na facebooku: "
},
"defaultAudioLanguage": "pl"
},
"status": {
"uploadStatus": "processed",
"privacyStatus": "public",
"license": "youtube",
"embeddable": true,
"publicStatsViewable": true,
"madeForKids": false
},
"statistics": {
"viewCount": "33035",
"likeCount": "1681",
"dislikeCount": "23",
"favoriteCount": "0",
"commentCount": "131"
},
"player": {
"embedHtml": "<iframe width=\"480\" height=\"270\" src=\"//www.youtube.com/embed/Tn2TgqkrCng\" frameborder=\"0\" allow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>"
},
"topicDetails": {
"relevantTopicIds": [
"/m/02vxn",
"/m/025zzc",
"/m/0403l3g"
],
"topicCategories": [
"https://en.wikipedia.org/wiki/Action_game",
"https://en.wikipedia.org/wiki/Film",
"https://en.wikipedia.org/wiki/Role-playing_video_game"
]
},
"recordingDetails": {}
}
],
"pageInfo": {
"totalResults": 1,
"resultsPerPage": 1
}
}
As you can see, there is no info about game title. Has anyone struggled with this and knows the way how to do it?
Someone has already posted the same question here, but it looks like everyone misunderstood him, there is no correct answer and I have no rep to comment in this thread.
As people noticed, there isn't any YouTube Data API v3 endpoint providing you the game associated with the YouTube video.
However by downloading the video webpage and looking for in the source code of the webpage we can find it. Here is a Python 3 script retrieving the game title associated with the YouTube video if there is any:
import urllib.request
def getURL(url):
return urllib.request.urlopen(url).read().decode('utf-8')
videoId = 'oua2xCWTK48'
url = 'https://www.youtube.com/watch?v=' + videoId
content = getURL(url)
prefix = '}]},"title":{"simpleText":"'
if prefix in content:
gameName = content.split(prefix)[1].split('"')[0]
print(gameName)

YouTube LiveBroadcast remove bound stream and transition lifeCycleStatus from "ready" to "live" or "created"

I have an issue with trying to transition a YouTube LiveBroadcast from ready to live. The liveBroadcast looks like this
{
"kind": "youtube#liveBroadcast",
"id": "VALID_ID",
"snippet": {
"publishedAt": "2018-03-12T13:11:52.000Z",
"channelId": "CHANNEL_ID",
"title": "Test",
"description": "Live stream",
"thumbnails": {
"default": {
"url": "URL",
"width": 120,
"height": 90
},
"medium": {
"url": "URL",
"width": 320,
"height": 180
},
"high": {
"url": "URL",
"width": 480,
"height": 360
},
"standard": {
"url": "URL",
"width": 640,
"height": 480
}
},
"scheduledStartTime": "2018-03-12T13:26:23.000Z",
"isDefaultBroadcast": false,
"liveChatId": "LIVE_CHAT_ID"
},
"status": {
"lifeCycleStatus": "ready",
"privacyStatus": "private",
"recordingStatus": "notRecording"
},
"contentDetails": {
"boundStreamId": "BOUND_STREAM_ID",
"boundStreamLastUpdateTimeMs": "2018-03-12T13:26:19.065Z",
"monitorStream": {
"enableMonitorStream": false
},
"enableEmbed": false,
"enableDvr": true,
"enableContentEncryption": false,
"startWithSlate": false,
"recordFromStart": true,
"enableClosedCaptions": false,
"closedCaptionsType": "closedCaptionsDisabled",
"enableLowLatency": true,
"latencyPreference": "low",
"projection": "rectangular",
"enableAutoStart": false
}
I have replaced some private details with constants (but they are all valid).
I want to transition from ready to live which seems simple enough. Unfortunately I receive an error invalidTransition
{
"code" : 403,
"errors" : [ {
"domain" : "youtube.liveBroadcast",
"message" : "Invalid transition",
"reason" : "invalidTransition",
"extendedHelp" : "https://developers.google.com/youtube/v3/live/docs/liveBroadcasts/transition#params"
} ],
"message" : "Invalid transition"
}
This seems very odd and every time I encounter it I wonder why I cannot go from ready to live. At the same time I wonder why I cannot go back to the status created and remove a boundBroadcast.
Anyone know any way to transition to live from this state?

Mapping JSON Response to Model

New to the notion of Rails mapping, and would love to get some help on this from the stack overflow community.
Currently I have this JSON response from the Embedly API and don't really know how to map it to my very simple 'posts' model. I'm trying to get the image/title/url from the JSON response and map it into my database in the relevant fields, so in the JSON response below these would be 'original_url', 'image' and 'title'.
{
"provider_url": "http://piccsy.com",
"authors": [],
"provider_display": "piccsy.com",
"related": [],
"favicon_url": "http://piccsy.com/favicon.ico",
"keywords": [],
"app_links": [],
"original_url": "http://piccsy.com/2015/02/rihanna-sharks-harpers-bazaar-march-2015-photoshoot3",
"media": {},
"content": null,
"entities": [],
"provider_name": "Piccsy",
"type": "html",
"description": "Beautiful, inspirational and creative images from Piccsy. Thousands of Piccs from all our streams, for you to browse, enjoy and share with a friend.",
"embeds": [],
"images": [
{
"width": 728,
"url": "http://img2.piccsy.com/cache/images/56/8f/bed__396d8_cecf850824130_99f-post.jpg",
"height": 1092,
"caption": null,
"colors": [
{
"color": [
190,
211,
212
],
"weight": 0.3095703125
},
{
"color": [
114,
159,
171
],
"weight": 0.247314453125
},
{
"color": [
0,
52,
68
],
"weight": 0.244140625
},
{
"color": [
25,
99,
117
],
"weight": 0.198974609375
}
],
"entropy": 5.94797179868,
"size": 318918
},
{
"width": 200,
"url": "http://piccsy.com/piccsy/images/layout/logo/e02f43.200x200.jpg",
"height": 200,
"caption": null,
"colors": [
{
"color": [
215,
51,
67
],
"weight": 0.701904296875
},
{
"color": [
250,
252,
252
],
"weight": 0.298095703125
}
],
"entropy": 0.686638083774,
"size": 18691
}
],
"safe": true,
"offset": null,
"cache_age": 86065,
"lead": null,
"language": null,
"url": "http://piccsy.com/2015/02/rihanna-sharks-harpers-bazaar-march-2015-photoshoot3",
"title": "Rihanna-sharks-harpers-bazaar-march-2015-photoshoot3",
"favicon_colors": [
{
"color": [
208,
37,
38
],
"weight": 0.000244140625
},
{
"color": [
0,
0,
0
],
"weight": 0.000244140625
}
],
"published": null
}
My posts model contains very simple name, url and image fields which are all accepting strings. Any help on mapping this to a model would be brilliant, up till now I've only done very simple JSON responses and this one is a bit out of my league.
Thanks for your time.
You can just parse json response, and get required fields from it
json_response = '{your json response from api}'
response_hash = JSON.parse(json_response)
MyModel.create!(url: response_hash[:original_url], title: response_hash[:title])
But there is problem with images, response contains multiple images, so probably you should have ImageModel that belongs to MyModel, and MyModel has_many ImageModels.
Then you can do:
model = MyModel.create!(url: response_hash[:original_url], title: response_hash[:title])
response_hash[:images].each do |image|
model.images.create!(url: image[:url])
end

Resources