Browse Source

show videos with bitrate

Joystream Stats 2 years ago
parent
commit
fdd36077fa

+ 1 - 1
src/App.tsx

@@ -396,7 +396,7 @@ class App extends React.Component<IProps, IState> {
 
 
   async loadData() {
   async loadData() {
     console.debug(`Loading data`);
     console.debug(`Loading data`);
-    "status members assets providers councils council election workers categories channels proposals posts threads openings tokenomics transactions reports validators nominators staches stakes rewardPoints stars blocks hidden"
+    "status members assets providers councils council election workers categories channels proposals posts threads openings tokenomics transactions reports validators nominators staches stakes rewardPoints stars blocks hidden media"
       .split(" ")
       .split(" ")
       .map((key) => this.load(key));
       .map((key) => this.load(key));
     getTokenomics().then((tokenomics) => this.save(`tokenomics`, tokenomics));
     getTokenomics().then((tokenomics) => this.save(`tokenomics`, tokenomics));

+ 14 - 3
src/components/Dashboard/index.tsx

@@ -1,12 +1,23 @@
-import Events from '../Events'
+import Events from "../Events";
+import Media from "../Media";
 
 
 interface IProps extends IState {
 interface IProps extends IState {
   blocks: { id: number; events: any }[];
   blocks: { id: number; events: any }[];
 }
 }
 
 
 const Dashboard = (props: IProps) => {
 const Dashboard = (props: IProps) => {
-  const { save, hidden, selectEvent, blocks} = props
-  return <Events save={save} hidden={hidden} selectEvent={selectEvent} blocks={blocks} />
+  const { save, media, hidden, selectEvent, blocks } = props;
+  return (
+    <>
+      <Media save={save} media={media} />
+      <Events
+        save={save}
+        hidden={hidden}
+        selectEvent={selectEvent}
+        blocks={blocks}
+      />
+    </>
+  );
 };
 };
 
 
 export default Dashboard;
 export default Dashboard;

+ 86 - 0
src/components/Media/index.tsx

@@ -0,0 +1,86 @@
+import { useEffect } from "react";
+import { Badge } from "react-bootstrap";
+import axios from "axios";
+import { queryNode } from "../../config";
+
+const query = `query {
+  storageBags { id
+    distributionBuckets { operators { metadata{nodeEndpoint } } }
+    objects { id size  
+      videoMedia {id categoryId isCensored     isExplicit    isFeatured isPublic
+        thumbnailPhotoId duration title description
+        mediaMetadata {pixelWidth pixelHeight size encoding {codecName}}
+      }
+    }
+  }
+}`;
+
+const Media = (props: {}) => {
+  const { save, media } = props;
+
+  useEffect(() => {
+    media?.storageBags?.length ||
+      axios
+        .post(queryNode, { query })
+        .then(({ data }) => save("media", data.data))
+        .catch((e) => console.error(query, e.message));
+  }, [media?.storageBags?.length]);
+
+  return (
+    <div className="box">
+      <h2>Media</h2>
+      {media.storageBags?.length ? (
+        <div className="d-flex flex-wrap">
+          {media.storageBags
+            .reduce((objects, b) => {
+              b.objects.map((o) =>
+                objects.push({
+                  ...o,
+                  providers: b.distributionBuckets,
+                  bitrate: o.videoMedia?.duration
+                    ? (o.size / o.videoMedia.duration).toFixed()
+                    : 0,
+                })
+              );
+              return objects;
+            }, [])
+            .filter((o) => o.bitrate)
+            .sort((a, b) => b.bitrate - a.bitrate)
+            .map((o) => (
+              <Video key={o.id} {...o} />
+            ))}
+        </div>
+      ) : (
+        ""
+      )}
+    </div>
+  );
+};
+
+const Video = (props: {}) => {
+  const { id, title, videoMedia, bitrate, providers, size } = props;
+  const alt = `${id} ${videoMedia.title}`;
+  if (!providers?.length) return "";
+  const url = providers[0].operators[0].metadata.nodeEndpoint;
+  return (
+    <div
+      key={videoMedia.id}
+      className="text-left m-1"
+      style={{ width: "200px" }}
+    >
+      <img
+        className="d-block"
+        style={{ width: "200px" }}
+        src={url + "api/v1/assets/" + videoMedia.thumbnailPhotoId}
+        alt={alt}
+        title={alt}
+      />
+      <div>
+        {(bitrate / 1024 ** 2).toFixed(2)} mps / {(size / 1024 ** 2).toFixed()}
+        MB / {videoMedia.duration}s
+      </div>
+    </div>
+  );
+};
+
+export default Media;

+ 8 - 0
src/components/Media/index.tsx~

@@ -0,0 +1,8 @@
+import {useEffect, useState} from "react"
+import axios from "axios"
+
+const Media = () => {
+return "some media"
+}
+
+export default Media

+ 2 - 1
src/state.ts

@@ -29,7 +29,7 @@ export const initialState = {
   stashes: [],
   stashes: [],
   stars: {},
   stars: {},
   hideFooter: true,
   hideFooter: true,
-  hidden: ['ExtrinsicSuccess'],
+  hidden: ["ExtrinsicSuccess"],
   syncEvents: false,
   syncEvents: false,
   showStatus: false,
   showStatus: false,
   editKpi: false,
   editKpi: false,
@@ -41,4 +41,5 @@ export const initialState = {
     eraTotals: {},
     eraTotals: {},
     validators: {},
     validators: {},
   },
   },
+  media: {},
 };
 };