Invalid peer connection after network change in WebRTC media chat - webrtc

I am building web chat based on Janus media server. The problem occurs when I am testing in a mobile browser and change network (ex. disable/enable Wi-Fi).
After I do that, something is preventing establishing valid peer connection - when attaching media stream to video component there is no video and bitrate is 0. Also if I publish video from this mobile user, subscriber from another end can subscribe to my stream, but gets empty video/audio as well.
I've already tried triggering ICE renegotiation, it had no effect.
What is killing me is that usually people struggling fixing peer connection "smoothly" without page refresh and etc. In my case neither page refresh, nor Janus server restart, nor backend server restart doesn't help. This is one of the main reasons why I don't blame internal logic.
Problem gets fixed after some big amount of time (I usually test next day).
If I switch back to initial type of connection and resubscribe - video stream restores.
I am not expecting to get full solution here, but rather to get advice about what could cause given symptoms. I've already spent weeks on solving this bit.
here is subscriber handle info from admin monitor:
{
"session_id": 5720008786817209,
"session_last_activity": 6209682888251,
"session_transport": "janus.transport.http",
"handle_id": 6533528277151528,
"opaque_id": "sfutest-680291",
"loop-running": true,
"created": 6209682084107,
"current_time": 6209693977397,
"plugin": "janus.plugin.videoroom",
"plugin_specific": {
"type": "subscriber",
"room": 681365,
"private_id": 1730265710,
"feed_id": 4541903455858496,
"feed_display": "681365",
"media": {
"audio": true,
"audio-offered": true,
"video": true,
"video-offered": true,
"data": false,
"data-offered": true
},
"simulcast": {
"substream": -1,
"substream-target": 2,
"temporal-layer": -1,
"temporal-layer-target": 2
},
"hangingup": 0,
"destroyed": 0
},
"flags": {
"got-offer": true,
"got-answer": true,
"negotiated": true,
"processing-offer": false,
"starting": true,
"ice-restart": false,
"ready": true,
"stopped": false,
"alert": false,
"trickle": true,
"all-trickles": true,
"resend-trickles": false,
"trickle-synced": false,
"data-channels": false,
"has-audio": true,
"has-video": true,
"new-datachan-sdp": false,
"rfc4588-rtx": true,
"cleaning": false
},
"agent-created": 6209682284915,
"ice-mode": "full",
"ice-role": "controlling",
"sdps": {
"profile": "UDP/TLS/RTP/SAVPF",
"local": "v=0\r\no=- 1596975263019095 1 IN IP4 185.12.12.24\r\ns=VideoRoom 681365\r\nt=0 0\r\na=group:BUNDLE audio video\r\na=msid-semantic: WMS janus\r\nm=audio 9 UDP/TLS/RTP/SAVPF 111\r\nc=IN IP4 185.12.12.24\r\na=sendonly\r\na=mid:audio\r\na=rtcp-mux\r\na=ice-ufrag:sCux\r\na=ice-pwd:NK9E7vrPjeXDO2Q0DL3hIf\r\na=ice-options:trickle\r\na=fingerprint:sha-256 39:45:8D:E3:AB:4E:6D:55:63:07:16:39:14:FF:C1:8F:8C:3A:C1:32:FF:B8:2D:B5:42:C0:99:06:DB:BE:71:43\r\na=setup:actpass\r\na=rtpmap:111 opus/48000/2\r\na=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\na=extmap:2 urn:ietf:params:rtp-hdrext:sdes:mid\r\na=rtcp-fb:111 transport-cc\r\na=msid:janus janusa0\r\na=ssrc:3513017309 cname:janus\r\na=ssrc:3513017309 msid:janus janusa0\r\na=ssrc:3513017309 mslabel:janus\r\na=ssrc:3513017309 label:janusa0\r\na=candidate:1 1 udp 2015363327 185.12.12.24 58146 typ host\r\na=end-of-candidates\r\nm=video 9 UDP/TLS/RTP/SAVPF 96 97\r\nc=IN IP4 185.12.12.24\r\na=sendonly\r\na=mid:video\r\na=rtcp-mux\r\na=ice-ufrag:sCux\r\na=ice-pwd:NK9E7vrPjeXDO2Q0DL3hIf\r\na=ice-options:trickle\r\na=fingerprint:sha-256 39:45:8D:E3:AB:4E:6D:55:63:07:16:39:14:FF:C1:8F:8C:3A:C1:32:FF:B8:2D:B5:42:C0:99:06:DB:BE:71:43\r\na=setup:actpass\r\na=rtpmap:96 VP8/90000\r\na=rtcp-fb:96 ccm fir\r\na=rtcp-fb:96 nack\r\na=rtcp-fb:96 nack pli\r\na=rtcp-fb:96 goog-remb\r\na=extmap:2 urn:ietf:params:rtp-hdrext:sdes:mid\r\na=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\r\na=extmap:12 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay\r\na=extmap:13 urn:3gpp:video-orientation\r\na=rtpmap:97 rtx/90000\r\na=fmtp:97 apt=96\r\na=ssrc-group:FID 163753807 2929619259\r\na=msid:janus janusv0\r\na=ssrc:163753807 cname:janus\r\na=ssrc:163753807 msid:janus janusv0\r\na=ssrc:163753807 mslabel:janus\r\na=ssrc:163753807 label:janusv0\r\na=ssrc:2929619259 cname:janus\r\na=ssrc:2929619259 msid:janus janusv0\r\na=ssrc:2929619259 mslabel:janus\r\na=ssrc:2929619259 label:janusv0\r\na=candidate:1 1 udp 2015363327 185.12.12.24 58146 typ host\r\na=end-of-candidates\r\n",
"remote": "v=0\r\no=- 2846574689702018810 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=group:BUNDLE audio video\r\na=msid-semantic: WMS\r\nm=audio 9 UDP/TLS/RTP/SAVPF 111\r\nc=IN IP4 0.0.0.0\r\na=rtcp:9 IN IP4 0.0.0.0\r\na=ice-ufrag:iTKh\r\na=ice-pwd:YcBYvuoYtPN74wLGsmRYZPkC\r\na=ice-options:trickle\r\na=fingerprint:sha-256 44:62:26:8A:9B:2C:35:82:62:07:1C:36:1B:3D:84:B0:D7:1C:A2:9D:A3:57:D0:41:E8:D6:F9:D8:9A:77:04:FE\r\na=setup:active\r\na=mid:audio\r\na=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\na=extmap:2 urn:ietf:params:rtp-hdrext:sdes:mid\r\na=recvonly\r\na=rtcp-mux\r\na=rtpmap:111 opus/48000/2\r\na=rtcp-fb:111 transport-cc\r\na=fmtp:111 minptime=10;useinbandfec=1\r\nm=video 9 UDP/TLS/RTP/SAVPF 96 97\r\nc=IN IP4 0.0.0.0\r\na=rtcp:9 IN IP4 0.0.0.0\r\na=ice-ufrag:iTKh\r\na=ice-pwd:YcBYvuoYtPN74wLGsmRYZPkC\r\na=ice-options:trickle\r\na=fingerprint:sha-256 44:62:26:8A:9B:2C:35:82:62:07:1C:36:1B:3D:84:B0:D7:1C:A2:9D:A3:57:D0:41:E8:D6:F9:D8:9A:77:04:FE\r\na=setup:active\r\na=mid:video\r\na=extmap:13 urn:3gpp:video-orientation\r\na=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\r\na=extmap:12 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay\r\na=extmap:2 urn:ietf:params:rtp-hdrext:sdes:mid\r\na=recvonly\r\na=rtcp-mux\r\na=rtpmap:96 VP8/90000\r\na=rtcp-fb:96 goog-remb\r\na=rtcp-fb:96 ccm fir\r\na=rtcp-fb:96 nack\r\na=rtcp-fb:96 nack pli\r\na=rtpmap:97 rtx/90000\r\na=fmtp:97 apt=96\r\n"
},
"queued-packets": 0,
"streams": [
{
"id": 1,
"ready": -1,
"ssrc": {
"audio": 3513017309,
"video": 163753807,
"video-rtx": 2929619259
},
"direction": {
"audio-send": true,
"audio-recv": false,
"video-send": true,
"video-recv": false
},
"extensions": {
"urn:ietf:params:rtp-hdrext:sdes:mid": 2,
"http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01": 3,
"urn:ietf:params:rtp-hdrext:ssrc-audio-level": 1,
"urn:3gpp:video-orientation": 13
},
"bwe": {
"twcc": true,
"twcc-ext-id": 3
},
"nack-queue-ms": 200,
"rtcp_stats": {
"audio": {
"base": 48000,
"rtt": 0,
"lost": 0,
"lost-by-remote": 0,
"jitter-local": 0,
"jitter-remote": 0,
"in-link-quality": 0,
"in-media-link-quality": 0,
"out-link-quality": 0,
"out-media-link-quality": 0
},
"video": {
"base": 90000,
"rtt": 0,
"lost": 0,
"lost-by-remote": 0,
"jitter-local": 0,
"jitter-remote": 0,
"in-link-quality": 0,
"in-media-link-quality": 0,
"out-link-quality": 0,
"out-media-link-quality": 0
}
},
"components": [
{
"id": 1,
"state": "ready",
"connected": 6209682688321,
"local-candidates": [
"1 1 udp 2015363327 185.12.12.24 58146 typ host"
],
"remote-candidates": [
"remote1 1 udp 1853759231 188.26.223.217 59505 typ prflx raddr 188.26.223.217 rport 59505\r\n",
"1287214573 1 udp 2122194687 192.168.1.131 59505 typ host generation 0 ufrag iTKh network-id 1 network-cost 10",
"4213993584 1 udp 2122262783 2a0c:5a80:190e:2b00:6d56:6bd7:468e:1b1b 53024 typ host generation 0 ufrag iTKh network-id 2 network-cost 10"
],
"selected-pair": "185.12.12.24:58146 [host,udp] <-> 188.26.223.217:59505 [prflx,udp]",
"dtls": {
"fingerprint": "39:45:8D:E3:AB:4E:6D:55:63:07:16:39:14:FF:C1:8F:8C:3A:C1:32:FF:B8:2D:B5:42:C0:99:06:DB:BE:71:43",
"remote-fingerprint": "44:62:26:8A:9B:2C:35:82:62:07:1C:36:1B:3D:84:B0:D7:1C:A2:9D:A3:57:D0:41:E8:D6:F9:D8:9A:77:04:FE",
"remote-fingerprint-hash": "sha-256",
"dtls-role": "passive",
"dtls-state": "connected",
"retransmissions": 0,
"valid": true,
"srtp-profile": "SRTP_AEAD_AES_256_GCM",
"ready": true,
"handshake-started": 6209682688345,
"connected": 6209682837110,
"sctp-association": false
},
"in_stats": {
"audio_packets": 0,
"audio_bytes": 0,
"audio_bytes_lastsec": 0,
"do_audio_nacks": false,
"video_packets": 0,
"video_bytes": 0,
"video_bytes_lastsec": 0,
"do_video_nacks": true,
"video_nacks": 0,
"video_retransmissions": 0,
"data_packets": 4,
"data_bytes": 1056
},
"out_stats": {
"audio_packets": 0,
"audio_bytes": 0,
"audio_bytes_lastsec": 0,
"audio_nacks": 0,
"video_packets": 0,
"video_bytes": 0,
"video_bytes_lastsec": 0,
"video_nacks": 0,
"data_packets": 2,
"data_bytes": 1259
}
}
]
}
]
}

Related

Create a oauth-token for integration tests

We want to create a "long lasting" token for integration testing purposes. We are using a keycloak for creating tokens normally. But I don't see a possibility to create tokens with no expiration, so that reoccuring integration tests on dev-stage can be done without interuption.
What would you suggest for such automatically repeating testing regarding oauth?
All access token should expire at some point, that why the rfc details the use of refresh token, wich can be used indefinitly to keep your service running, the basic idea is that when you request an access token, you'll get an access token plus a refresh token, and when the first token expires, you send it to the keycloak server and it will regenerate a new access token and a new refresh token.
In practice, you should use your token as long as its valid (since you know in advance it lifespan), and when your token is about to expire you resend the request using the refresh token.
src: RFC oauth2
How about make longer time(a couple of days) for access token before start integration test?
After finish integration test, return to default time(5 minutes).
This is my demo test steps
Get master of realm access token and assign token variable
Get my-realm's realm data
this is default my-realm's setting data
{
"id": "my-realm",
"realm": "my-realm",
"notBefore": 0,
"defaultSignatureAlgorithm": "RS256",
"revokeRefreshToken": false,
"refreshTokenMaxReuse": 0,
"accessTokenLifespan": 300,
"accessTokenLifespanForImplicitFlow": 900,
"ssoSessionIdleTimeout": 1800,
"ssoSessionMaxLifespan": 36000,
"ssoSessionIdleTimeoutRememberMe": 0,
"ssoSessionMaxLifespanRememberMe": 0,
"offlineSessionIdleTimeout": 2592000,
"offlineSessionMaxLifespanEnabled": false,
"offlineSessionMaxLifespan": 5184000,
"clientSessionIdleTimeout": 0,
"clientSessionMaxLifespan": 0,
"clientOfflineSessionIdleTimeout": 0,
"clientOfflineSessionMaxLifespan": 0,
"accessCodeLifespan": 60,
"accessCodeLifespanUserAction": 300,
"accessCodeLifespanLogin": 1800,
"actionTokenGeneratedByAdminLifespan": 43200,
"actionTokenGeneratedByUserLifespan": 300,
"oauth2DeviceCodeLifespan": 600,
"oauth2DevicePollingInterval": 5,
"enabled": true,
"sslRequired": "external",
"registrationAllowed": false,
"registrationEmailAsUsername": false,
"rememberMe": false,
"verifyEmail": false,
"loginWithEmailAllowed": true,
"duplicateEmailsAllowed": false,
"resetPasswordAllowed": false,
"editUsernameAllowed": false,
"bruteForceProtected": false,
"permanentLockout": false,
"maxFailureWaitSeconds": 900,
"minimumQuickLoginWaitSeconds": 60,
"waitIncrementSeconds": 60,
"quickLoginCheckMilliSeconds": 1000,
"maxDeltaTimeSeconds": 43200,
"failureFactor": 30,
"defaultRole": {
"id": "3798f9f6-3383-474e-997e-123d9b534ae4",
"name": "default-roles-my-realm",
"description": "${role_default-roles}",
"composite": true,
"clientRole": false,
"containerId": "my-realm"
},
"requiredCredentials": [
"password"
],
"otpPolicyType": "totp",
"otpPolicyAlgorithm": "HmacSHA1",
"otpPolicyInitialCounter": 0,
"otpPolicyDigits": 6,
"otpPolicyLookAheadWindow": 1,
"otpPolicyPeriod": 30,
"otpSupportedApplications": [
"FreeOTP",
"Google Authenticator"
],
"webAuthnPolicyRpEntityName": "keycloak",
"webAuthnPolicySignatureAlgorithms": [
"ES256"
],
"webAuthnPolicyRpId": "",
"webAuthnPolicyAttestationConveyancePreference": "not specified",
"webAuthnPolicyAuthenticatorAttachment": "not specified",
"webAuthnPolicyRequireResidentKey": "not specified",
"webAuthnPolicyUserVerificationRequirement": "not specified",
"webAuthnPolicyCreateTimeout": 0,
"webAuthnPolicyAvoidSameAuthenticatorRegister": false,
"webAuthnPolicyAcceptableAaguids": [],
"webAuthnPolicyPasswordlessRpEntityName": "keycloak",
"webAuthnPolicyPasswordlessSignatureAlgorithms": [
"ES256"
],
"webAuthnPolicyPasswordlessRpId": "",
"webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified",
"webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified",
"webAuthnPolicyPasswordlessRequireResidentKey": "not specified",
"webAuthnPolicyPasswordlessUserVerificationRequirement": "not specified",
"webAuthnPolicyPasswordlessCreateTimeout": 0,
"webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false,
"webAuthnPolicyPasswordlessAcceptableAaguids": [],
"browserSecurityHeaders": {
"contentSecurityPolicyReportOnly": "",
"xContentTypeOptions": "nosniff",
"xRobotsTag": "none",
"xFrameOptions": "SAMEORIGIN",
"contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';",
"xXSSProtection": "1; mode=block",
"strictTransportSecurity": "max-age=31536000; includeSubDomains"
},
"smtpServer": {},
"eventsEnabled": false,
"eventsListeners": [
"jboss-logging"
],
"enabledEventTypes": [],
"adminEventsEnabled": false,
"adminEventsDetailsEnabled": false,
"identityProviders": [],
"identityProviderMappers": [],
"internationalizationEnabled": false,
"supportedLocales": [],
"browserFlow": "browser",
"registrationFlow": "registration",
"directGrantFlow": "direct grant",
"resetCredentialsFlow": "reset credentials",
"clientAuthenticationFlow": "clients",
"dockerAuthenticationFlow": "docker auth",
"attributes": {
"cibaBackchannelTokenDeliveryMode": "poll",
"cibaExpiresIn": "120",
"cibaAuthRequestedUserHint": "login_hint",
"oauth2DeviceCodeLifespan": "600",
"oauth2DevicePollingInterval": "5",
"parRequestUriLifespan": "60",
"cibaInterval": "5"
},
"userManagedAccessAllowed": false,
"clientProfiles": {
"profiles": []
},
"clientPolicies": {
"policies": []
}
}
Extend logger period of access(2 days) token lifetime
I changed accessTokenLifespan value from 300 to 172800 (= 3600 * 24 *2) seconds
use PUT method for update realm data
In the UI of Keycloak, the Access Token Lifespan will be changed into 2 days
the Status of API call should be return 204 (No Content)
Run your integration tests
Return back 2.'s default(or previous) lifetime

Bitcoin / DefiChain RPC rawTransaction

Hello i try to figure out how to encode normal rpc calls in an raw transaction.
Till now my problem is that i dont know what the hex must contain as string.
f.e.
rpc command: "method: 'compositeswap' {'from':'MyAddress','tokenFrom':'MyToken1','amountFrom':'0.001','to':'Address','tokenTo':'Token2','maxPrice':'0.01'}"
There seems to be OP-Codes to exists like OP_DEFI_TX_COMPOSITE_SWAP
how does the chain knows to execute an operation with params?
i tried to figure it out by trying to decode an actual transaction from the test wallet:
from the part
"scriptPubKey": {
"asm": "OP_RETURN 446654786917a914721d5b1c58d38af7b6797b385b6ac291b002f88c870000e1f5050000000017a914721d5b1c58d38af7b6797b385b6ac291b002f88c870b0000000000000000c74e71050000000000",
"hex": "6a4c50446654786917a914721d5b1c58d38af7b6797b385b6ac291b002f88c870000e1f5050000000017a914721d5b1c58d38af7b6797b385b6ac291b002f88c870b0000000000000000c74e71050000000000",
"type": "nulldata"
},
of
{
"txid": "9a98d693d4c5107647131ee1bb7a5b0cce0fcdbe390c9609a71f4b71157e39dc",
"hash": "a18a6fd4abf0ba1885febcf37a333b1d1f34b4de954f13538a6619b1d7b20042",
"version": 4,
"size": 309,
"vsize": 228,
"weight": 909,
"locktime": 0,
"vin": [
{
"txid": "9e1140197138ba5e247ab3b3f1f4881bf7be624a939073d9795242caf3634409",
"vout": 1,
"scriptSig": {
"asm": "0014451be7ab94ccd7eff0a33ab8fe997a75c62eb7dd",
"hex": "160014451be7ab94ccd7eff0a33ab8fe997a75c62eb7dd"
},
"txinwitness": [
"30440220552d8aa4e129f566bfe083b780e1dcf67a3ca0176e07407912451371f597bc620220698c6ac483e021b78c7d7bf42e14f1c619618d1941cf12fec7cf8302ece6d3ae01",
"03c7d2dbe5ee429de5d88e8594cda6ceb84268ebbf9d0b16b33664e999307f33e8"
],
"sequence": 4294967295
}
],
"vout": [
{
"value": 0,
"n": 0,
"scriptPubKey": {
"asm": "OP_RETURN 446654786917a914721d5b1c58d38af7b6797b385b6ac291b002f88c870000e1f5050000000017a914721d5b1c58d38af7b6797b385b6ac291b002f88c870b0000000000000000c74e71050000000000",
"hex": "6a4c50446654786917a914721d5b1c58d38af7b6797b385b6ac291b002f88c870000e1f5050000000017a914721d5b1c58d38af7b6797b385b6ac291b002f88c870b0000000000000000c74e71050000000000",
"type": "nulldata"
},
"tokenId": 0
},
{
"value": 183.03901748,
"n": 1,
"scriptPubKey": {
"asm": "OP_HASH160 721d5b1c58d38af7b6797b385b6ac291b002f88c OP_EQUAL",
"hex": "a914721d5b1c58d38af7b6797b385b6ac291b002f88c87",
"reqSigs": 1,
"type": "scripthash",
"addresses": [
"tgfbETCK2kYyvsnHbS41v9aicQzAXLsz9B"
]
},
"tokenId": 0
}
]
}
the
OP_RETURN 446654786917a914721d5b1c58d38af7b6797b385b6ac291b002f88c870000e1f5050000000017a914721d5b1c58d38af7b6797b385b6ac291b002f88c870b0000000000000000c74e71050000000000
cant be decoded sucessfully back into a string.
does s.o know what kind of encoding it is?
tried
bytess=bytes.fromhex("446654786917a914721d5b1c58d38af7b6797b385b6ac291b002f88c870000e1f5050000000017a914721d5b1c58d38af7b6797b385b6ac291b002f88c870b0000000000000000c74e71050000000000")
print(bytess.decode("latin-1"))
but only get
INFO (MainThread) 14.05.2022 22:02:39 DfTxi©r
INFO (MainThread) 14.05.2022 22:02:39 [
INFO (MainThread) 14.05.2022 22:02:39 XÓŠ÷¶y{8[j‘°øŒ‡ áõ ©r
You can't just decode the string after the OP Code. It is a concatenation of several input parameters depending on the function.
In your example
6a4c50446654786917a914721d5b1c58d38af7b6797b385b6ac291b002f88c870000e1f5050000000017a914721d5b1c58d38af7b6797b385b6ac291b002f88c870b0000000000000000c74e71050000000000
6a is OP_RETURN
4c50 is Number of bytes following (in HEX)
44665478 is "DfTx" in HEX
6917a914721d5b1c58d38af7b6797b385b6ac291b002f88c870000e1f5050000000017a914721d5b1c58d38af7b6797b385b6ac291b002f88c870b0000000000000000c74e71050000000000 = the parameters from your json. For your address you need Base58 (in this case) or Bech32 encoding to get the hex (some backward engineering necessary).
The part with lots of zeros is the amount/maxPrice.
The tokens are inserted by their IDs not the name.
I am thinking about writing a guide. So far, I am afraid you have to do some backward engineering. Hope this helps a little bit

Seaweedfs volume management

I have 2 questions concerning a Seaweedfs cluster we have running. The leader is started with the following command:
/usr/local/bin/weed server -ip=192.168.13.154 -ip.bind=192.168.13.154 -dir=/opt/seaweedfs/volume-1,/opt/seaweedfs/volume-2,/opt/seaweedfs/volume-3 -master.dir=/opt/seaweedfs/master -master.peers=192.168.13.154:9333,192.168.13.155:9333,192.168.13.156:9333 -volume.max=30,30,30 -filer=true -s3=true -metrics.address=192.168.13.84:9091
Question 1
I created a master.toml file using weed scaffold -config=master:
[master.maintenance]
# periodically run these scripts are the same as running them from 'weed shell'
scripts = """
ec.encode -fullPercent=95 -quietFor=1h
ec.rebuild -force
ec.balance -force
volume.balance -force
"""
sleep_minutes = 17 # sleep minutes between each script execution
However the maintenance scripts seem to fail because
shell failed to keep connected to localhost:9333: rpc error: code = Unavailable desc = all SubConns are in TransientFailure, latest connection error: connection error: desc = "transport: Error while dialing dial tcp [::1]:19333: connect: connection refused"
This makes sense since the master is bound to ip 192.168.13.154 and the maintenance script tries to connect to localhost. How can I specificy the master ip in the master.toml file?
Question 2
The amount of volumes seems to grow faster than the amount of disk space used. For example on the .154 server there are only 11 free volumes. But looking at the disk space there should be much more.
Status:
{
"Topology": {
"DataCenters": [
{
"Free": 16,
"Id": "DefaultDataCenter",
"Max": 270,
"Racks": [
{
"DataNodes": [
{
"EcShards": 0,
"Free": 0,
"Max": 90,
"PublicUrl": "192.168.13.155:8080",
"Url": "192.168.13.155:8080",
"Volumes": 90
},
{
"EcShards": 0,
"Free": 11,
"Max": 90,
"PublicUrl": "192.168.13.154:8080",
"Url": "192.168.13.154:8080",
"Volumes": 79
},
{
"EcShards": 0,
"Free": 5,
"Max": 90,
"PublicUrl": "192.168.13.156:8080",
"Url": "192.168.13.156:8080",
"Volumes": 85
}
],
"Free": 16,
"Id": "DefaultRack",
"Max": 270
}
]
}
],
"Free": 16,
"Max": 270,
"layouts": [
...
]
},
"Version": "30GB 1.44"
}
Disk (192.168.13.154):
/dev/sdb1 1007G 560G 397G 59% /opt/seaweedfs/volume-1
/dev/sdc1 1007G 542G 414G 57% /opt/seaweedfs/volume-2
/dev/sdd1 1007G 398G 559G 42% /opt/seaweedfs/volume-3
Is this related to the maintenance scripts not running properly, or is there something else I'm not understanding correctly?
Question 1: Added a fix https://github.com/chrislusf/seaweedfs/commit/56244fb9a13c75616aa8a9232c62d1b896906e98
Question 2: Likely related to master leadership changes.

Access value of variant object in shopify

I have Object of the product please check below. can you please let me know that how can I get the variants value. I have tried to get variant.inventory_quantity but can not get
{
"id": 9129131982,
"title": "Universal Suction Base Adapter",
"handle": "usb-universal-suction-base-adapter",
"description": "\u003cp\u003eAll F-Machines are supplied with a Vac-u-Lock style adapter as standard, which are compatible with Doc Johnson Vac-u-Lock dildos and toys.\u003c\/p\u003e\n\u003cp\u003eF-Machine brings you the brand new Universal Suction Base (USB). This revolutionary bolt on system integrates your favourite suction (\/flared) base sex toys with either your F-Machine Pro II or Gigolo. With this fantastic innovation from the pervy engineers at F-Machine, you can now choose which style of toy to use on your machine and discover new possibilities for sexual play \u0026amp; fantasy.\u003c\/p\u003e\n\u003cul\u003e\n\u003cli\u003eDesigned to fit all F-Machine 10 mm thrust rods\u003c\/li\u003e\n\u003cli\u003eInjection moulded from shatter proof plastic composite material\u003c\/li\u003e\n\u003cli\u003eOver-moulded brass threaded insert for maximum durability and holding capacity\u003c\/li\u003e\n\u003cli\u003eOption of dildo retention via suction, O-rings or Velcro straps (or combination)\u003c\/li\u003e\n\u003cli\u003eFits dildos with suction base diameter up to 88 mm (when installed)\u003c\/li\u003e\n\u003cli\u003eSupplied with a comprehensive O-ring set and range of Velcro straps to fit most dildo sizes\u003c\/li\u003e\n\u003cli\u003eCan be used with Double Trouble\u003c\/li\u003e\n\u003c\/ul\u003e\n\u003cp\u003e\u003cstrong\u003ePlease note:\u003c\/strong\u003e F-Machine fucking machine and toys are not included (for illustration purposes only).\u003c\/p\u003e\n\u003cp\u003e \u003c\/p\u003e",
"published_at": "2016-11-25T16:29:00-11:00",
"created_at": "2016-11-25T16:36:50-11:00",
"vendor": "F-Machine",
"type": "",
"tags": [],
"price": 4900,
"price_min": 4900,
"price_max": 4900,
"available": true,
"price_varies": false,
"compare_at_price": null,
"compare_at_price_min": 0,
"compare_at_price_max": 0,
"compare_at_price_varies": false,
"variants": [{
"id": 31980207054,
"title": "Default Title",
"option1": "Default Title",
"option2": null,
"option3": null,
"sku": "",
"requires_shipping": true,
"taxable": true,
"featured_image": null,
"available": true,
"name": "Universal Suction Base Adapter",
"public_title": null,
"options": ["Default Title"],
"price": 4900,
"weight": 600,
"compare_at_price": null,
"inventory_quantity": 2,
"inventory_management": "shopify",
"inventory_policy": "deny",
"barcode": ""
}],
inventory_quantity was deprecated recently. Instead, you'll have to use:
https://help.shopify.com/en/api/reference/inventory/inventorylevel

Media Source Extensions appendBuffer of WebM stream in random order

I am trying to achieve video downloading in parallel from multiple sources. However MSE appendBuffer method always fails when not following sequence order of video file.
I would like to append parts in random order and play video "as soon as possible".
I was exploring SourceBuffer mode property as well as timestampOffset. None of those were helpful.
I am wondering if source webm file i have could be in "not supported format" for such a task (sequential approach works fine).
source video file
Thank you for any advices.
UPDATE:
I tried to analyse well known example video file and i figured out that it is possible to append parts of it out of order. Seems like it is necessary to follow Cluster byte ranges:
<Cluster type="list" offset="4357">
<Timecode type="uint" value="0"/>
<SimpleBlock type="binary" size="7723" trackNum="1" timecode="0" presentationTimecode="0" flags="80"/>
<SimpleBlock type="binary" size="5" trackNum="2" timecode="0" presentationTimecode="0" flags="80"/>
...
</Cluster>
<Cluster type="list" offset="16187">
<Timecode type="uint" value="385"/>
<SimpleBlock type="binary" size="5" trackNum="2" timecode="0" presentationTimecode="385" flags="80"/>
<SimpleBlock type="binary" size="4968" trackNum="1" timecode="13" presentationTimecode="398" flags="80"/>
...
</Cluster>
After digging into webm format specification, compiling libwebm tools and studying DASH i finally figured out how to make MSE appendBuffer working in any order!
ffmpeg -i result.webm -g 10 -c:v libvpx resultClusters.webm (you can also use libvpx-vp9)
mkvmuxer_sample -i resultClusters.webm -o resultRepaired.webm
mse_json_manifest resultRepaired.webm >> manifest.json
You will get on stdout something like:
{
"type": "video/webm; codecs=\"vp8\"",
"duration": 27771.000000,
"init": { "offset": 0, "size": 258},
"media": [
{ "offset": 258, "size": 54761, "timecode": 0.000000 },
{ "offset": 55019, "size": 166431, "timecode": 2.048000 },
{ "offset": 221450, "size": 49258, "timecode": 4.130000 },
{ "offset": 270708, "size": 29677, "timecode": 6.148000 },
{ "offset": 300385, "size": 219929, "timecode": 8.232000 },
{ "offset": 520314, "size": 25132, "timecode": 10.335000 },
{ "offset": 545446, "size": 180777, "timecode": 12.440000 },
{ "offset": 726223, "size": 76107, "timecode": 14.471000 },
{ "offset": 802330, "size": 376557, "timecode": 14.794000 },
{ "offset": 1178887, "size": 247138, "timecode": 16.877000 },
{ "offset": 1426025, "size": 78468, "timecode": 18.915000 },
{ "offset": 1504493, "size": 25614, "timecode": 20.991000 },
{ "offset": 1530107, "size": 368277, "timecode": 23.093000 },
{ "offset": 1898384, "size": 382847, "timecode": 25.097000 },
{ "offset": 2281231, "size": 10808, "timecode": 27.135000 }
]
}
Now all you have to do is firstly load metadata xhr.setRequestHeader("Range", "bytes=0-257"); and then in ANY ORDER all other segments. E.g. second segment range is 55019-221449 bytes.
Explanation:
The most important thing is ffmpeg reencoding with group of frames set to the size of cluster you would like to have. In this example i choose pretty low threshold (each 10 frames) but you can choose higher causing fewer clusters are generated (less items in "media" array).
After that you have to fix cues in the classic way (using sample_muxer from libwebm) and you are ready to go.
Tested on: Chrome 51, Firefox 47.