InvalidTransition from Youtube Live Streaming API - youtube-api

I got good result for Broadcast
&youtube.LiveBroadcastListResponse{
Etag: "\"aaa-3cgQ/bbb\"",
EventId: "",
Items: {
&youtube.LiveBroadcast{
ContentDetails: &youtube.LiveBroadcastContentDetails{
BoundStreamId: "ccc-ddd",
BoundStreamLastUpdateTimeMs: "2017-01-30T09:02:38.977Z",
ClosedCaptionsType: "closedCaptionsDisabled",
EnableClosedCaptions: false,
EnableContentEncryption: true,
EnableDvr: true,
EnableEmbed: true,
EnableLowLatency: false,
MonitorStream: &youtube.MonitorStreamInfo{
BroadcastStreamDelayMs: 1,
EmbedHtml: "<iframe width=\"425\" height=\"344\" src=\"https://www.youtube.com/embed/eee?autoplay=1&livemonitor=1\" frameborder=\"0\" allowfullscreen></iframe>",
EnableMonitorStream: true,
ForceSendFields: nil,
NullFields: nil,
},
Projection: "rectangular",
RecordFromStart: true,
StartWithSlate: true,
ForceSendFields: nil,
NullFields: nil,
},
Etag: "\"aaa-3cgQ/fff\"",
Id: "eee",
Kind: "youtube#liveBroadcast",
Snippet: &youtube.LiveBroadcastSnippet{
ActualEndTime: "",
ActualStartTime: "",
ChannelId: "UCccc-ggg",
Description: "",
IsDefaultBroadcast: false,
LiveChatId: "Cg0KC0hfUkFFaW4zUUVJ",
PublishedAt: "2017-01-30T04:59:19.000Z",
ScheduledEndTime: "2017-01-31T02:00:00.000Z",
ScheduledStartTime: "2017-01-31T00:00:00.000Z",
Thumbnails: &youtube.ThumbnailDetails{
Default: &youtube.Thumbnail{
Height: 90,
Url: "https://i.ytimg.com/vi/eee/default_live.jpg",
Width: 120,
ForceSendFields: nil,
NullFields: nil,
},
High: &youtube.Thumbnail{
Height: 360,
Url: "https://i.ytimg.com/vi/eee/hqdefault_live.jpg",
Width: 480,
ForceSendFields: nil,
NullFields: nil,
},
Maxres: (*youtube.Thumbnail)(nil),
Medium: &youtube.Thumbnail{
Height: 180,
Url: "https://i.ytimg.com/vi/eee/mqdefault_live.jpg",
Width: 320,
ForceSendFields: nil,
NullFields: nil,
},
Standard: (*youtube.Thumbnail)(nil),
ForceSendFields: nil,
NullFields: nil,
},
Title: "Test broadcast from iOS",
ForceSendFields: nil,
NullFields: nil,
},
Statistics: (*youtube.LiveBroadcastStatistics)(nil),
Status: &youtube.LiveBroadcastStatus{
LifeCycleStatus: "ready",
LiveBroadcastPriority: "",
PrivacyStatus: "unlisted",
RecordingStatus: "notRecording",
ForceSendFields: nil,
NullFields: nil,
},
TopicDetails: (*youtube.LiveBroadcastTopicDetails)(nil),
ServerResponse: googleapi.ServerResponse{},
ForceSendFields: nil,
NullFields: nil,
},
},
Kind: "youtube#liveBroadcastListResponse",
NextPageToken: "",
PageInfo: &youtube.PageInfo{
ResultsPerPage: 5,
TotalResults: 0,
ForceSendFields: nil,
NullFields: nil,
},
PrevPageToken: "",
TokenPagination: (*youtube.TokenPagination)(nil),
VisitorId: "",
ServerResponse: googleapi.ServerResponse{
HTTPStatusCode: 200,
Header: {
"Server": {"GSE"},
"Expires": {"Mon, 30 Jan 2017 11:34:04 GMT"},
"Date": {"Mon, 30 Jan 2017 11:34:04 GMT"},
"Cache-Control": {"private, max-age=0, must-revalidate, no-transform"},
"Etag": {"\"aaa-3cgQ/bbb\""},
"Vary": {"Origin", "X-Origin"},
"Content-Type": {"application/json; charset=UTF-8"},
"X-Frame-Options": {"SAMEORIGIN"},
"X-Content-Type-Options": {"nosniff"},
"X-Xss-Protection": {"1; mode=block"},
"Content-Length": {"1989"},
"Alt-Svc": {"quic=\":443\"; ma=2592000; v=\"35,34\""},
},
},
ForceSendFields: nil,
NullFields: nil,
}
And also good response for Stream:
&youtube.LiveStreamListResponse{
Etag: "\"aaa-3cgQ/iii-Sg\"",
EventId: "",
Items: {
&youtube.LiveStream{
Cdn: &youtube.CdnSettings{
Format: "360p",
FrameRate: "30fps",
IngestionInfo: &youtube.IngestionInfo{
BackupIngestionAddress: "rtmp://b.rtmp.youtube.com/live2?backup=1",
IngestionAddress: "rtmp://a.rtmp.youtube.com/live2",
StreamName: "3zjv-0cp2-wtet-0779",
ForceSendFields: nil,
NullFields: nil,
},
IngestionType: "rtmp",
Resolution: "360p",
ForceSendFields: nil,
NullFields: nil,
},
ContentDetails: (*youtube.LiveStreamContentDetails)(nil),
Etag: "\"aaa-3cgQ/hhh\"",
Id: "ccc-ddd",
Kind: "youtube#liveStream",
Snippet: &youtube.LiveStreamSnippet{
ChannelId: "UCccc-ggg",
Description: "",
IsDefaultStream: false,
PublishedAt: "2017-01-30T09:02:39.000Z",
Title: "Broadcast: eee App: 16 ID: 16",
ForceSendFields: nil,
NullFields: nil,
},
Status: &youtube.LiveStreamStatus{
HealthStatus: &youtube.LiveStreamHealthStatus{
ConfigurationIssues: nil,
LastUpdateTimeSeconds: 0x0,
Status: "good",
ForceSendFields: nil,
NullFields: nil,
},
StreamStatus: "active",
ForceSendFields: nil,
NullFields: nil,
},
ServerResponse: googleapi.ServerResponse{},
ForceSendFields: nil,
NullFields: nil,
},
},
Kind: "youtube#liveStreamListResponse",
NextPageToken: "",
PageInfo: &youtube.PageInfo{
ResultsPerPage: 5,
TotalResults: 0,
ForceSendFields: nil,
NullFields: nil,
},
PrevPageToken: "",
TokenPagination: (*youtube.TokenPagination)(nil),
VisitorId: "",
ServerResponse: googleapi.ServerResponse{
HTTPStatusCode: 200,
Header: {
"Date": {"Mon, 30 Jan 2017 11:35:54 GMT"},
"X-Frame-Options": {"SAMEORIGIN"},
"X-Xss-Protection": {"1; mode=block"},
"Content-Length": {"1008"},
"Content-Type": {"application/json; charset=UTF-8"},
"X-Content-Type-Options": {"nosniff"},
"Server": {"GSE"},
"Alt-Svc": {"quic=\":443\"; ma=2592000; v=\"35,34\""},
"Expires": {"Mon, 30 Jan 2017 11:35:54 GMT"},
"Cache-Control": {"private, max-age=0, must-revalidate, no-transform"},
"Etag": {"\"aaa-3cgQ/iii-Sg\""},
"Vary": {"Origin", "X-Origin"},
},
},
ForceSendFields: nil,
NullFields: nil,
}
But when I tried to transition to testing for eee, it shows an error:
&googleapi.Error{
Code: 403,
Message: "Invalid transition",
Body: "{\n \"error\": {\n \"errors\": [\n {\n \"domain\": \"youtube.liveBroadcast\",\n \"reason\": \"invalidTransition\",\n \"message\": \"Invalid transition\",\n \"extendedHelp\": \"https://developers.google.com/youtube/v3/live/docs/liveBroadcasts/transition#params\"\n }\n ],\n \"code\": 403,\n \"message\": \"Invalid transition\"\n }\n}\n",
Header: {},
Errors: {
{Reason:"invalidTransition", Message:"Invalid transition"},
},
}
From the doc, it said that: The live broadcast can't transition from its current status to the requested status., that is from ready to testing, The stream status is already active and health is good, is there anything I missed?

Apparently it's caused by the stream resolution is too low, the camera is 360x640 (vertical >__<), creating new stream with 720p resolution solves this problem.

Related

Loop through JSON Object Swift 5

I am trying to iterate through a JSON object and obtain specific values in the swift programming language.
I am receiving a JSON like so
let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String : Any],
let charges = json["charges"] as? [String:Any]
json:
{
object: 'list',
data: [
{
id: 'ch_1IWQEfKn7R1M6tqnhrpyIhMk',
object: 'charge',
amount: 555,
amount_captured: 555,
amount_refunded: 0,
application: 'ca_IXRQuoBh5mSJXXpEccXssma6Oz0u3HjX',
application_fee: 'fee_1IWQEfKn7R1M6tqnvTHQeSEF',
application_fee_amount: 6,
balance_transaction: 'txn_1IWQEfKn7R1M6tqnkK9LCNuM',
billing_details: [Object],
calculated_statement_descriptor: 'TEST ACCOUNT',
captured: true,
created: 1616090777,
currency: 'usd',
customer: null,
description: null,
destination: null,
dispute: null,
disputed: false,
failure_code: null,
failure_message: null,
fraud_details: {},
invoice: null,
livemode: false,
metadata: {},
on_behalf_of: null,
order: null,
outcome: [Object],
paid: true,
payment_intent: 'pi_1IWQEeKn7R1M6tqnYbGfFCzg',
payment_method: 'pm_1IWQEeKn7R1M6tqnKLxSg6vZ',
payment_method_details: [Object],
receipt_email: null,
receipt_number: null,
receipt_url: 'https://pay.stripe.com/receipts/acct_1ISouBKn7R1M6tqn/ch_1IWQEfKn7R1M6tqnhrpyIhMk/rcpt_J8hdy05N6VfOmRECdumpti8Jiljz2Et',
refunded: false,
refunds: [Object],
review: null,
shipping: null,
source: null,
source_transfer: null,
statement_descriptor: null,
statement_descriptor_suffix: null,
status: 'succeeded',
transfer_data: null,
transfer_group: null
},
{
id: 'ch_1IU62QKn7R1M6tqnbXXlOpch',
object: 'charge',
amount: 5599,
amount_captured: 5599,
amount_refunded: 0,
application: 'ca_IXRQuoBh5mSJXXpEccXssma6Oz0u3HjX',
application_fee: 'fee_1IU62RKn7R1M6tqnLle3zblA',
application_fee_amount: 56,
balance_transaction: 'txn_1IU62RKn7R1M6tqn3ttu9F3N',
billing_details: [Object],
calculated_statement_descriptor: 'TEST ACCOUNT',
captured: true,
created: 1615536482,
currency: 'usd',
customer: null,
description: null,
destination: null,
dispute: null,
disputed: false,
failure_code: null,
failure_message: null,
fraud_details: {},
invoice: null,
livemode: false,
metadata: {},
on_behalf_of: null,
order: null,
outcome: [Object],
paid: true,
payment_intent: 'pi_1IU62NKn7R1M6tqnWSOLJVge',
payment_method: 'pm_1IU62PKn7R1M6tqnIyOUgUMX',
payment_method_details: [Object],
receipt_email: null,
receipt_number: null,
receipt_url: 'https://pay.stripe.com/receipts/acct_1ISouBKn7R1M6tqn/ch_1IU62QKn7R1M6tqnbXXlOpch/rcpt_J6Id30gjIhQU6AWPBHgUXoujbhFOTyf',
refunded: false,
refunds: [Object],
review: null,
shipping: null,
source: null,
source_transfer: null,
statement_descriptor: null,
statement_descriptor_suffix: null,
status: 'succeeded',
transfer_data: null,
transfer_group: null
},
{
id: 'ch_1IU60cKn7R1M6tqny9o2NV5W',
object: 'charge',
amount: 1000,
amount_captured: 1000,
amount_refunded: 0,
application: 'ca_IXRQuoBh5mSJXXpEccXssma6Oz0u3HjX',
application_fee: 'fee_1IU60cKn7R1M6tqn95nUHETe',
application_fee_amount: 10,
balance_transaction: 'txn_1IU60cKn7R1M6tqnZKNbSEXf',
billing_details: [Object],
calculated_statement_descriptor: 'TEST ACCOUNT',
captured: true,
created: 1615536370,
currency: 'usd',
customer: null,
description: null,
destination: null,
dispute: null,
disputed: false,
failure_code: null,
failure_message: null,
fraud_details: {},
invoice: null,
livemode: false,
metadata: {},
on_behalf_of: null,
order: null,
outcome: [Object],
paid: true,
payment_intent: 'pi_1IU60ZKn7R1M6tqnrUSK1TQD',
payment_method: 'pm_1IU60bKn7R1M6tqnAUHQXqJG',
payment_method_details: [Object],
receipt_email: null,
receipt_number: null,
receipt_url: 'https://pay.stripe.com/receipts/acct_1ISouBKn7R1M6tqn/ch_1IU60cKn7R1M6tqny9o2NV5W/rcpt_J6Ib5PEZQzEgyXWoOwKcxZ9x7mByCVu',
refunded: false,
refunds: [Object],
review: null,
shipping: null,
source: null,
source_transfer: null,
statement_descriptor: null,
statement_descriptor_suffix: null,
status: 'succeeded',
transfer_data: null,
transfer_group: null
}
],
has_more: true,
url: '/v1/charges'
}
How can I iterate through the JSON object to receive "amount", "currency", and "id".
For example PSUEDO:
for item in charges {
print(item["amount"])
print(item["currency"])
print(item["id"])
}
I may be initializing the json improperly such as
json["charges"] as? [String:Any]
You shouldn't use try ? - This throws away errors. Always use do/try/catch so that you handle any errors that occur, even if you just print them.
JSONSerialization and decoding JSON to arrays and dictionaries isn't best practice. It is much better to create suitable structs that conform to Codable and use JSONDecoder.
struct Response: Codable {
var object: String
var hasMore: Bool
var data: [ResponseData]
var url: String
enum CodingKeys: String, CodingKey {
case object
case hasMore = "has_more"
case url
case data
}
}
struct ResponseData: Codable {
var amount: Int
var currency: String
var id: String
}
For simplicity I have't added all of the properties to the ResponseData struct, just the ones you have said you are interested in
do {
let json = try JSONDecoder().decode(Response.self, from: data)
json.data.forEach { charge in
print(charge.id)
print(charge.currency)
print(charge.ammount)
}
} catch {
print("Error! \(error)")
}

Error Status 400 When Uploading to Youtube API v3

I keep getting an error when trying to POST to Youtube v3 API.
I'm trying to get a response URI, so I can upload a Youtube video.
This is the documentation I'm referencing: https://developers.google.com/youtube/v3/docs/videos/insert#go
Does anyone know what I'm doing wrong? Error log is below.
My code:
axios({
method: 'POST',
baseURL: 'https://www.googleapis.com',
url: '/upload/youtube/v3/videos',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Content-Length': 167,
'X-Upload-Content-Length': 302080,
'X-Upload-Content-Type': 'video/mp4',
'Authorization': `Bearer <MY_ACCESS_TOKEN>`, // has my actual access_token
},
params: {
'uploadType': 'resumable',
'key': <MY_API_KEY>, // has my actual app API key
'part': 'snippet,status'
},
data: {
'snippet': {
'title': 'Test Upload 1',
'description': 'Test Description 1',
'tags': ['tag1', 'tag2'],
},
'status': {
'privacyStatus': 'private',
}
}
})
.then(response => {
res.json(response.data);
})
.catch(err => console.log(err));
Error Log:
Error: Request failed with status code 400
at createError (/mnt/e/Dev/20200316_youtube_api/node_modules/axios/lib/core/createError.js:16:15)
at settle (/mnt/e/Dev/20200316_youtube_api/node_modules/axios/lib/core/settle.js:17:12)
at IncomingMessage.handleStreamEnd (/mnt/e/Dev/20200316_youtube_api/node_modules/axios/lib/adapters/http.js:236:11)
at IncomingMessage.emit (events.js:323:22)
at endReadableNT (_stream_readable.js:1204:12)
at processTicksAndRejections (internal/process/task_queues.js:84:21) {
config: {
url: '/upload/youtube/v3/videos',
method: 'post',
params: {
key: '<MY_API_KEY>',
part: 'snippet,status'
},
data: '{"snippet":{"title":"Test Upload 1","description":"Test Description 1","tags":["tag1","tag2"]},"status":{"privacyStatus":"private"}}',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'Content-Length': 132,
'X-Upload-Content-Length': 302080,
'X-Upload-Content-Type': 'video/mp4',
Authorization: 'Bearer <MY_ACCESS_TOKEN>',
'User-Agent': 'axios/0.19.2'
},
baseURL: 'https://www.googleapis.com',
transformRequest: [ [Function: transformRequest] ],
transformResponse: [ [Function: transformResponse] ],
timeout: 0,
adapter: [Function: httpAdapter],
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
validateStatus: [Function: validateStatus]
},
request: ClientRequest {
_events: [Object: null prototype] {
socket: [Function],
abort: [Function],
aborted: [Function],
error: [Function],
timeout: [Function],
prefinish: [Function: requestOnPrefinish]
},
_eventsCount: 6,
_maxListeners: undefined,
outputData: [],
outputSize: 0,
writable: true,
_last: true,
chunkedEncoding: false,
shouldKeepAlive: false,
useChunkedEncodingByDefault: true,
sendDate: false,
_removedConnection: false,
_removedContLen: false,
_removedTE: false,
_contentLength: null,
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
socket: TLSSocket {
_tlsOptions: [Object],
_secureEstablished: true,
_securePending: false,
_newSessionPending: false,
_controlReleased: true,
_SNICallback: null,
servername: 'www.googleapis.com',
alpnProtocol: false,
authorized: true,
authorizationError: null,
encrypted: true,
_events: [Object: null prototype],
_eventsCount: 9,
connecting: false,
_hadError: false,
_parent: null,
_host: 'www.googleapis.com',
_readableState: [ReadableState],
readable: true,
_maxListeners: undefined,
_writableState: [WritableState],
writable: false,
allowHalfOpen: false,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: undefined,
_server: null,
ssl: [TLSWrap],
_requestCert: true,
_rejectUnauthorized: true,
parser: null,
_httpMessage: [Circular],
[Symbol(res)]: [TLSWrap],
[Symbol(asyncId)]: 6,
[Symbol(kHandle)]: [TLSWrap],
[Symbol(lastWriteQueueSize)]: 0,
[Symbol(timeout)]: null,
[Symbol(kBuffer)]: null,
[Symbol(kBufferCb)]: null,
[Symbol(kBufferGen)]: null,
[Symbol(kCapture)]: false,
[Symbol(kBytesRead)]: 0,
[Symbol(kBytesWritten)]: 0,
[Symbol(connect-options)]: [Object]
},
connection: TLSSocket {
_tlsOptions: [Object],
_secureEstablished: true,
_securePending: false,
_newSessionPending: false,
_controlReleased: true,
_SNICallback: null,
servername: 'www.googleapis.com',
alpnProtocol: false,
authorized: true,
authorizationError: null,
encrypted: true,
_events: [Object: null prototype],
_eventsCount: 9,
connecting: false,
_hadError: false,
_parent: null,
_host: 'www.googleapis.com',
_readableState: [ReadableState],
readable: true,
_maxListeners: undefined,
_writableState: [WritableState],
writable: false,
allowHalfOpen: false,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: undefined,
_server: null,
ssl: [TLSWrap],
_requestCert: true,
_rejectUnauthorized: true,
parser: null,
_httpMessage: [Circular],
[Symbol(res)]: [TLSWrap],
[Symbol(asyncId)]: 6,
[Symbol(kHandle)]: [TLSWrap],
[Symbol(lastWriteQueueSize)]: 0,
[Symbol(timeout)]: null,
[Symbol(kBuffer)]: null,
[Symbol(kBufferCb)]: null,
[Symbol(kBufferGen)]: null,
[Symbol(kCapture)]: false,
[Symbol(kBytesRead)]: 0,
[Symbol(kBytesWritten)]: 0,
[Symbol(connect-options)]: [Object]
},
_header: 'POST /upload/youtube/v3/videos?key=<MY_API_KEY>&part=snippet,status HTTP/1.1\r\n' +
'Accept: application/json\r\n' +
'Content-Type: application/json\r\n' +
'Content-Length: 132\r\n' +
'X-Upload-Content-Length: 302080\r\n' +
'X-Upload-Content-Type: video/mp4\r\n' +
'Authorization: Bearer <MY_ACCESS_TOKEN>\r\n' +
'User-Agent: axios/0.19.2\r\n' +
'Host: www.googleapis.com\r\n' +
'Connection: close\r\n' +
'\r\n',
_onPendingData: [Function: noopPendingOutput],
agent: Agent {
_events: [Object: null prototype],
_eventsCount: 2,
_maxListeners: undefined,
defaultPort: 443,
protocol: 'https:',
options: [Object],
requests: {},
sockets: [Object],
freeSockets: {},
keepAliveMsecs: 1000,
keepAlive: false,
maxSockets: Infinity,
maxFreeSockets: 256,
maxCachedSessions: 100,
_sessionCache: [Object],
[Symbol(kCapture)]: false
},
socketPath: undefined,
method: 'POST',
insecureHTTPParser: undefined,
path: '/upload/youtube/v3/videos?key=<MY_API_KEY>&part=snippet,status',
_ended: true,
res: IncomingMessage {
_readableState: [ReadableState],
readable: false,
_events: [Object: null prototype],
_eventsCount: 3,
_maxListeners: undefined,
socket: [TLSSocket],
connection: [TLSSocket],
httpVersionMajor: 1,
httpVersionMinor: 1,
httpVersion: '1.1',
complete: true,
headers: [Object],
rawHeaders: [Array],
trailers: {},
rawTrailers: [],
aborted: false,
upgrade: false,
url: '',
method: null,
statusCode: 400,
statusMessage: 'Bad Request',
client: [TLSSocket],
_consuming: false,
_dumped: false,
req: [Circular],
responseUrl: 'https://www.googleapis.com/upload/youtube/v3/videos?key=<MY_API_KEY>&part=snippet,status',
redirects: [],
[Symbol(kCapture)]: false
},
aborted: false,
timeoutCb: null,
upgradeOrConnect: false,
parser: null,
maxHeadersCount: null,
reusedSocket: false,
_redirectable: Writable {
_writableState: [WritableState],
writable: true,
_events: [Object: null prototype],
_eventsCount: 2,
_maxListeners: undefined,
_options: [Object],
_redirectCount: 0,
_redirects: [],
_requestBodyLength: 132,
_requestBodyBuffers: [],
_onNativeResponse: [Function],
_currentRequest: [Circular],
_currentUrl: 'https://www.googleapis.com/upload/youtube/v3/videos?key=<MY_API_KEY>&part=snippet,status',
[Symbol(kCapture)]: false
},
[Symbol(kCapture)]: false,
[Symbol(kNeedDrain)]: false,
[Symbol(corked)]: 0,
[Symbol(kOutHeaders)]: [Object: null prototype] {
accept: [Array],
'content-type': [Array],
'content-length': [Array],
'x-upload-content-length': [Array],
'x-upload-content-type': [Array],
authorization: [Array],
'user-agent': [Array],
host: [Array]
}
},
response: {
status: 400,
statusText: 'Bad Request',
headers: {
'x-guploader-uploadid': '<REPONSE_ID_THAT_I_REMOVED>',
vary: 'Origin, X-Origin',
'content-type': 'application/json; charset=UTF-8',
'content-length': '353',
date: 'Sun, 07 Jun 2020 22:45:50 GMT',
server: 'UploadServer',
'alt-svc': 'h3-27=":443"; ma=2592000,h3-25=":443"; ma=2592000,h3-T050=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q049=":443";
ma=2592000,h3-Q048=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"',
connection: 'close'
},
config: {
url: '/upload/youtube/v3/videos',
method: 'post',
params: [Object],
data: '{"snippet":{"title":"Test Upload 1","description":"Test Description 1","tags":["tag1","tag2"]},"status":{"privacyStatus":"private"}}',
headers: [Object],
baseURL: 'https://www.googleapis.com',
transformRequest: [Array],
transformResponse: [Array],
timeout: 0,
adapter: [Function: httpAdapter],
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
validateStatus: [Function: validateStatus]
},
request: ClientRequest {
_events: [Object: null prototype],
_eventsCount: 6,
_maxListeners: undefined,
outputData: [],
outputSize: 0,
writable: true,
_last: true,
chunkedEncoding: false,
shouldKeepAlive: false,
useChunkedEncodingByDefault: true,
sendDate: false,
_removedConnection: false,
_removedContLen: false,
_removedTE: false,
_contentLength: null,
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
socket: [TLSSocket],
connection: [TLSSocket],
_header: 'POST /upload/youtube/v3/videos?key=<MY_API_KEY>&part=snippet,status HTTP/1.1\r\n' +
'Accept: application/json\r\n' +
'Content-Type: application/json\r\n' +
'Content-Length: 132\r\n' +
'X-Upload-Content-Length: 302080\r\n' +
'X-Upload-Content-Type: video/mp4\r\n' +
'Authorization: Bearer <MY_ACCESS_TOKEN>\r\n' +
'User-Agent: axios/0.19.2\r\n' +
'Host: www.googleapis.com\r\n' +
'Connection: close\r\n' +
'\r\n',
_onPendingData: [Function: noopPendingOutput],
agent: [Agent],
socketPath: undefined,
method: 'POST',
insecureHTTPParser: undefined,
path: '/upload/youtube/v3/videos?key=<MY_API_KEY>&part=snippet,status',
_ended: true,
res: [IncomingMessage],
aborted: false,
timeoutCb: null,
upgradeOrConnect: false,
parser: null,
maxHeadersCount: null,
reusedSocket: false,
_redirectable: [Writable],
[Symbol(kCapture)]: false,
[Symbol(kNeedDrain)]: false,
[Symbol(corked)]: 0,
[Symbol(kOutHeaders)]: [Object: null prototype]
},
data: { error: [Object] }
},
isAxiosError: true,
toJSON: [Function]
}
That request is not for uploading video, that request returns a url to which the video can be uploaded.

How do i create and sent a JSON to the server using Alamofire?

I want to sent a JSON to the server,with details of user and options selected by the user. Currently i just save those in simple arrays.
I want to create a JSON and sent it to the server. Normally i can just add each those fields on Parameter with Alamofire. But here i have an issue is that, the number of fields depend on the number of users(or passenger count).
I haven't done this type before and i am a newbie into iOS developing.
{
"contactPerson": {
"email": {
"email": "memine#gmail.com",
"markedForSendingRezInfo": false,
"preferred": false,
"shareMarketInd": false
},
"personName": {
"givenName": "Me",
"shareMarketInd": false,
"surname": "Mine"
},
"phoneNumber": {
"countryCode": "93",
"markedForSendingRezInfo": false,
"preferred": false,
"shareMarketInd": false,
"subscriberNumber": "123456789"
},
"shareMarketInd": false,
"useForInvoicing": false
},
"curr": "USD",
"flight1": "{fligh1Info}",
"flight2": "{flight2Info}",
"passengers": [{
"accompaniedByInfant": true,
"birthDate": {
"day": 6,
"fractionalSecond": 0.000,
"hour": 0,
"minute": 0,
"month": 9,
"orig_day": 6,
"orig_fracSeconds": 0.000,
"orig_hour": 0,
"orig_minute": 0,
"orig_month": 9,
"orig_second": 0,
"orig_timezone": 330,
"orig_year": 1991,
"second": 0,
"timezone": 330,
"year": 1991
},
"hasStrecher": false,
"parentSequence": 0,
"passengerTypeCode": "ADLT",
"personName": {
"givenName": "some",
"nameTitle": "Mr.",
"shareMarketInd": false,
"surname": "guy"
},
"requestedSeatCount": 1,
"shareMarketInd": false,
"unaccompaniedMinor": false
}, {
"accompaniedByInfant": false,
"birthDate": {
"day": 10,
"fractionalSecond": 0.000,
"hour": 0,
"minute": 0,
"month": 10,
"orig_day": 10,
"orig_fracSeconds": 0.000,
"orig_hour": 0,
"orig_minute": 0,
"orig_month": 10,
"orig_second": 0,
"orig_timezone": 330,
"orig_year": 2010,
"second": 0,
"timezone": 330,
"year": 2010
},
"hasStrecher": false,
"parentSequence": 0,
"passengerTypeCode": "CHLD",
"personName": {
"givenName": "some",
"shareMarketInd": false,
"surname": "child"
},
"requestedSeatCount": 1,
"shareMarketInd": false,
"unaccompaniedMinor": false
}, {
"accompaniedByInfant": false,
"birthDate": {
"day": 1,
"fractionalSecond": 0.000,
"hour": 0,
"minute": 0,
"month": 1,
"orig_day": 1,
"orig_fracSeconds": 0.000,
"orig_hour": 0,
"orig_minute": 0,
"orig_month": 1,
"orig_second": 0,
"orig_timezone": 330,
"orig_year": 2018,
"second": 0,
"timezone": 330,
"year": 2018
},
"hasStrecher": false,
"parentSequence": 0,
"passengerTypeCode": "INFT",
"personName": {
"givenName": "some",
"shareMarketInd": false,
"surname": "kid"
},
"requestedSeatCount": 1,
"shareMarketInd": false,
"unaccompaniedMinor": false
}],
"pwd": "password",
"requestPurpose": "MODIFY_PERMANENTLY_AND_CALC",
"unm": "username"
}
This is my JSON. Here number of flight1 flight2 .... depends on number of flights picked by the user.
and number of objects inside passengers depends on number of passengers selected by the user.
How do i do this part?
Try to create a dictionary of [String: Any] type like below example.
let param : [String: Any] = ["contactPerson": [ "email":[ "email": "text#mail.com"], "markedForSendingRezInfo": false], "personName": [], "curr": "USD", "flight1" : [], "flight2" : [] ]
You can add key value in param as per request parameter requirement. then pass this param to alamofire request param.
You need to add your data in Dictionary
Swift5
let dictData = ["name": "vicky", "phoneNumber": "01234567"]
let encoder = JSONEncoder()
if let jsonData = try? encoder.encode(dictData) {
if let jsonString = String(data: jsonData, encoding: .utf8) {
print(jsonString)
}
}

Youtube channel livestream embedded doesn't work

I'm using iframe for embed youtube channel in my site, but it shows "An error ocurred. Please try again.". Strangely, if I set another channel ID it works.
The channel ID that doesn't work
The channel ID that works
I copied the debug information just in case:
{
"cpn": "hWjSQIlGKWCb1Abv",
"vct": "0.000",
"vd": "NaN",
"vpl": "",
"vbu": "",
"vpa": "1",
"vsk": "0",
"ven": "0",
"vpr": "1",
"vrs": "0",
"vns": "0",
"vec": "null",
"vvol": "1",
"creationTime": 65805,
"totalVideoFrames": 0,
"droppedVideoFrames": 0,
"corruptedVideoFrames": 0,
"state": "80",
"debug_error": {
"errorCode": "api.invalidparam",
"errorDetail": "invalidVideodata.1",
"message": "Se ha producido un error. Vuelve a intentarlo más tarde.",
"messageKey": "GENERIC_WITHOUT_LINK",
"subreason": ""
},
"relative_loudness": "NaN",
"user_qual": "auto",
"0sz": false,
"op": "",
"yof": false,
"dis": "",
"gpu": "Intel_Iris_Pro_OpenGL_Engine",
"cgr": true,
"debug_playbackQuality": "unknown",
"debug_date": "Fri Nov 16 2018 14:20:11 GMT-0400 (hora de Bolivia)"
}
And this is the code I used:
player = new YT.Player('player', {
videoId: 'live_stream',
playerVars: {
channel: 'UCJC7T__QoftT5B3QkLUv7pQ',
controls: 0,
disablekb: 1,
fs: 0,
modestbranding: 1,
rel: 0,
showinfo: 0
},
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
Please, help me.

how to implement custom grouping in jqGrid

I'm starter in jqGrid, i write this code for Implement Grouping
$(function () {
var mydata = [
{ id: "11", invdate: "2007-10-01", name: "test", note: "note", amount: "200.00", tax: "10.00", total: "210.00" },
{ id: "12", invdate: "2007-10-02", name: "test2", note: "note2", amount: "300.00", tax: "20.00", total: "320.00" },
{ id: "13", invdate: "2007-09-01", name: "test3", note: "note3", amount: "400.00", tax: "30.00", total: "430.00" },
{ id: "14", invdate: "2007-10-04", name: "test", note: "note", amount: "200.00", tax: "10.00", total: "210.00" },
{ id: "15", invdate: "2007-10-05", name: "test2", note: "note2", amount: "300.00", tax: "20.00", total: "320.00" },
{ id: "16", invdate: "2007-09-06", name: "test3", note: "note3", amount: "400.00", tax: "30.00", total: "430.00" },
{ id: "17", invdate: "2007-10-04", name: "test", note: "note", amount: "200.00", tax: "10.00", total: "210.00" },
{ id: "18", invdate: "2007-10-03", name: "test2", note: "note2", amount: "300.00", tax: "20.00", total: "320.00" },
{ id: "19", invdate: "2007-09-01", name: "test3", note: "note3", amount: "400.00", tax: "30.00", total: "430.00" },
{ id: "21", invdate: "2007-10-01", name: "test", note: "note", amount: "200.00", tax: "10.00", total: "210.00" },
{ id: "22", invdate: "2007-10-02", name: "test2", note: "note2", amount: "300.00", tax: "20.00", total: "320.00" },
{ id: "23", invdate: "2007-09-01", name: "test3", note: "note3", amount: "400.00", tax: "30.00", total: "430.00" },
{ id: "24", invdate: "2007-10-04", name: "test", note: "note", amount: "200.00", tax: "10.00", total: "210.00" },
{ id: "25", invdate: "2007-10-05", name: "test2", note: "note2", amount: "300.00", tax: "20.00", total: "320.00" },
{ id: "26", invdate: "2007-09-06", name: "test3", note: "note3", amount: "400.00", tax: "30.00", total: "430.00" },
{ id: "27", invdate: "2007-10-04", name: "test", note: "note", amount: "200.00", tax: "10.00", total: "210.00" },
{ id: "28", invdate: "2007-10-03", name: "test2", note: "note2", amount: "300.00", tax: "20.00", total: "320.00" },
{ id: "29", invdate: "2007-09-01", name: "test3", note: "note3", amount: "400.00", tax: "30.00", total: "430.00"}];
jQuery("#list48").jqGrid({
data: mydata,
datatype: "local",
height: 'auto',
rowNum: 30,
rowList: [10, 20, 30],
colNames: ['Inv No', 'Date', 'Client', 'Amount', 'Tax', 'Total', 'Notes'],
colModel: [
{ name: 'id', index: 'id', width: 60, sorttype: "int" },
{ name: 'invdate', index: 'invdate', width: 90, sorttype: "date", formatter: "date" },
{ name: 'name', index: 'name', width: 100, editable: true },
{ name: 'amount', index: 'amount', width: 80, align: "right", sorttype: "float", formatter: "number", editable: true },
{ name: 'tax', index: 'tax', width: 80, align: "right", sorttype: "float", editable: true },
{ name: 'total', index: 'total', width: 80, align: "right", sorttype: "float" },
{ name: 'note', index: 'note', width: 150, sortable: false}],
pager: "#plist48",
viewrecords: true,
sortname: 'name',
grouping: true,
groupingView: { groupField: ['name'] },
caption: "Grouping Array Data" });
});
and create this grid
i want set Grouping Dynamicaly.Such that user Drag Header Column and Drop in top box after that grid Grop such this picture
please help me for implement this senaryo
. thanks all
On the jqGrid side you need to use groupingRemove and groupingGroupBy methods to change grouping dynamic, you can read more about them in documentation.
For the UI part you should look at following interactions:
Draggable
Droppable
Sortable
The Shopping Cart sample in Droppable should give you a very good overview on how to approach the subject.
Now after all that theoretical informations, I have created a sample on jsFiddle for you: jqGrid dynamic drag-n-drop grouping. It needs some styling to look exactly as what you are looking for, but it should allow you to understand all the internals. If you need some comments on the code let me know - I can add them later.

Resources