Live video on the AT Protocol

Add seg size to segment.json

authored by Natalie B and committed by Eli Mallon 39fe00a0 9f30d974

+94 -5
+3 -3
js/app/components/mobile/ui.tsx
··· 14 } from "@streamplace/components"; 15 import { ChevronLeft, SwitchCamera, VolumeX } from "lucide-react-native"; 16 import { useEffect, useRef, useState } from "react"; 17 - import { Image, Pressable, TouchableWithoutFeedback } from "react-native"; 18 import Animated, { 19 useAnimatedStyle, 20 useSharedValue, ··· 93 94 return ( 95 <> 96 - <TouchableWithoutFeedback onPress={resetFadeTimer}> 97 <Animated.View 98 style={[ 99 layout.position.absolute, ··· 249 duration={5} 250 /> 251 </Animated.View> 252 - </TouchableWithoutFeedback> 253 254 {!isSelfAndNotLive && ( 255 <MobileChatPanel isPlayerRatioGreater={isPlayerRatioGreater} />
··· 14 } from "@streamplace/components"; 15 import { ChevronLeft, SwitchCamera, VolumeX } from "lucide-react-native"; 16 import { useEffect, useRef, useState } from "react"; 17 + import { Image, Pressable } from "react-native"; 18 import Animated, { 19 useAnimatedStyle, 20 useSharedValue, ··· 93 94 return ( 95 <> 96 + <Pressable onPress={resetFadeTimer}> 97 <Animated.View 98 style={[ 99 layout.position.absolute, ··· 249 duration={5} 250 /> 251 </Animated.View> 252 + </Pressable> 253 254 {!isSelfAndNotLive && ( 255 <MobileChatPanel isPlayerRatioGreater={isPlayerRatioGreater} />
+5
js/docs/src/content/docs/lex-reference/place-stream-segment.md
··· 28 | `creator` | `string` | ✅ | | Format: `did` | 29 | `video` | Array of [`#video`](#video) | ❌ | | | 30 | `audio` | Array of [`#audio`](#audio) | ❌ | | | 31 32 --- 33 ··· 144 "type": "ref", 145 "ref": "#audio" 146 } 147 } 148 } 149 }
··· 28 | `creator` | `string` | ✅ | | Format: `did` | 29 | `video` | Array of [`#video`](#video) | ❌ | | | 30 | `audio` | Array of [`#audio`](#audio) | ❌ | | | 31 + | `size` | `integer` | ❌ | The size of the segment in bytes | | 32 33 --- 34 ··· 145 "type": "ref", 146 "ref": "#audio" 147 } 148 + }, 149 + "size": { 150 + "type": "integer", 151 + "description": "The size of the segment in bytes" 152 } 153 } 154 }
+4
lexicons/place/stream/segment.json
··· 44 "type": "ref", 45 "ref": "#audio" 46 } 47 } 48 } 49 }
··· 44 "type": "ref", 45 "ref": "#audio" 46 } 47 + }, 48 + "size": { 49 + "type": "integer", 50 + "description": "The size of the segment in bytes" 51 } 52 } 53 }
+1
pkg/director/stream_session.go
··· 141 }() 142 aqt := aqtime.FromTime(not.Segment.StartTime) 143 ctx = log.WithLogValues(ctx, "segID", not.Segment.ID, "repoDID", not.Segment.RepoDID, "timestamp", aqt.FileSafeString()) 144 err := ss.mod.CreateSegment(not.Segment) 145 if err != nil { 146 return fmt.Errorf("could not add segment to database: %w", err)
··· 141 }() 142 aqt := aqtime.FromTime(not.Segment.StartTime) 143 ctx = log.WithLogValues(ctx, "segID", not.Segment.ID, "repoDID", not.Segment.RepoDID, "timestamp", aqt.FileSafeString()) 144 + not.Segment.MediaData.SizeB = len(not.Data) 145 err := ss.mod.CreateSegment(not.Segment) 146 if err != nil { 147 return fmt.Errorf("could not add segment to database: %w", err)
+1
pkg/media/validate.go
··· 85 RepoDID: repoDID, 86 StartTime: meta.StartTime.Time(), 87 Title: meta.Title, 88 MediaData: mediaData, 89 } 90 mm.newSegmentSubsMutex.RLock()
··· 85 RepoDID: repoDID, 86 StartTime: meta.StartTime.Time(), 87 Title: meta.Title, 88 + SizeB: len(buf), 89 MediaData: mediaData, 90 } 91 mm.newSegmentSubsMutex.RLock()
+5 -1
pkg/model/segment.go
··· 31 Video []*SegmentMediadataVideo `json:"video"` 32 Audio []*SegmentMediadataAudio `json:"audio"` 33 Duration int64 `json:"duration"` 34 } 35 36 // Scan scan value into Jsonb, implements sql.Scanner interface 37 - func (j *SegmentMediaData) Scan(value interface{}) error { 38 bytes, ok := value.([]byte) 39 if !ok { 40 return errors.New(fmt.Sprint("Failed to unmarshal JSONB value:", value)) ··· 59 RepoDID string `json:"repoDID" gorm:"index:latest_segments;column:repo_did"` 60 Repo *Repo `json:"repo,omitempty" gorm:"foreignKey:DID;references:RepoDID"` 61 Title string `json:"title"` 62 MediaData *SegmentMediaData `json:"mediaData,omitempty"` 63 } 64 ··· 74 return nil, fmt.Errorf("audio data is nil") 75 } 76 duration := s.MediaData.Duration 77 return &streamplace.Segment{ 78 LexiconTypeID: "place.stream.segment", 79 Creator: s.RepoDID, ··· 81 SigningKey: s.SigningKeyDID, 82 StartTime: string(aqt), 83 Duration: &duration, 84 Video: []*streamplace.Segment_Video{ 85 { 86 Codec: "h264",
··· 31 Video []*SegmentMediadataVideo `json:"video"` 32 Audio []*SegmentMediadataAudio `json:"audio"` 33 Duration int64 `json:"duration"` 34 + SizeB int `json:"sizeB"` 35 } 36 37 // Scan scan value into Jsonb, implements sql.Scanner interface 38 + func (j *SegmentMediaData) Scan(value any) error { 39 bytes, ok := value.([]byte) 40 if !ok { 41 return errors.New(fmt.Sprint("Failed to unmarshal JSONB value:", value)) ··· 60 RepoDID string `json:"repoDID" gorm:"index:latest_segments;column:repo_did"` 61 Repo *Repo `json:"repo,omitempty" gorm:"foreignKey:DID;references:RepoDID"` 62 Title string `json:"title"` 63 + SizeB int `json:"sizeB" gorm:"column:size_b"` 64 MediaData *SegmentMediaData `json:"mediaData,omitempty"` 65 } 66 ··· 76 return nil, fmt.Errorf("audio data is nil") 77 } 78 duration := s.MediaData.Duration 79 + sizei64 := int64(s.SizeB) 80 return &streamplace.Segment{ 81 LexiconTypeID: "place.stream.segment", 82 Creator: s.RepoDID, ··· 84 SigningKey: s.SigningKeyDID, 85 StartTime: string(aqt), 86 Duration: &duration, 87 + Size: &sizei64, 88 Video: []*streamplace.Segment_Video{ 89 { 90 Codec: "h264",
+73 -1
pkg/streamplace/cbor_gen.go
··· 558 } 559 560 cw := cbg.NewCborWriter(w) 561 - fieldCount := 8 562 563 if t.Audio == nil { 564 fieldCount-- 565 } 566 567 if t.Duration == nil { 568 fieldCount-- 569 } 570 ··· 597 } 598 if _, err := cw.WriteString(string(t.Id)); err != nil { 599 return err 600 } 601 602 // t.LexiconTypeID (string) (string) ··· 830 } 831 832 t.Id = string(sval) 833 } 834 // t.LexiconTypeID (string) (string) 835 case "$type":
··· 558 } 559 560 cw := cbg.NewCborWriter(w) 561 + fieldCount := 9 562 563 if t.Audio == nil { 564 fieldCount-- 565 } 566 567 if t.Duration == nil { 568 + fieldCount-- 569 + } 570 + 571 + if t.Size == nil { 572 fieldCount-- 573 } 574 ··· 601 } 602 if _, err := cw.WriteString(string(t.Id)); err != nil { 603 return err 604 + } 605 + 606 + // t.Size (int64) (int64) 607 + if t.Size != nil { 608 + 609 + if len("size") > 1000000 { 610 + return xerrors.Errorf("Value in field \"size\" was too long") 611 + } 612 + 613 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("size"))); err != nil { 614 + return err 615 + } 616 + if _, err := cw.WriteString(string("size")); err != nil { 617 + return err 618 + } 619 + 620 + if t.Size == nil { 621 + if _, err := cw.Write(cbg.CborNull); err != nil { 622 + return err 623 + } 624 + } else { 625 + if *t.Size >= 0 { 626 + if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(*t.Size)); err != nil { 627 + return err 628 + } 629 + } else { 630 + if err := cw.WriteMajorTypeHeader(cbg.MajNegativeInt, uint64(-*t.Size-1)); err != nil { 631 + return err 632 + } 633 + } 634 + } 635 + 636 } 637 638 // t.LexiconTypeID (string) (string) ··· 866 } 867 868 t.Id = string(sval) 869 + } 870 + // t.Size (int64) (int64) 871 + case "size": 872 + { 873 + 874 + b, err := cr.ReadByte() 875 + if err != nil { 876 + return err 877 + } 878 + if b != cbg.CborNull[0] { 879 + if err := cr.UnreadByte(); err != nil { 880 + return err 881 + } 882 + maj, extra, err := cr.ReadHeader() 883 + if err != nil { 884 + return err 885 + } 886 + var extraI int64 887 + switch maj { 888 + case cbg.MajUnsignedInt: 889 + extraI = int64(extra) 890 + if extraI < 0 { 891 + return fmt.Errorf("int64 positive overflow") 892 + } 893 + case cbg.MajNegativeInt: 894 + extraI = int64(extra) 895 + if extraI < 0 { 896 + return fmt.Errorf("int64 negative overflow") 897 + } 898 + extraI = -1 - extraI 899 + default: 900 + return fmt.Errorf("wrong type for int64 field: %d", maj) 901 + } 902 + 903 + t.Size = (*int64)(&extraI) 904 + } 905 } 906 // t.LexiconTypeID (string) (string) 907 case "$type":
+2
pkg/streamplace/streamsegment.go
··· 22 Id string `json:"id" cborgen:"id"` 23 // signingKey: The DID of the signing key used for this segment 24 SigningKey string `json:"signingKey" cborgen:"signingKey"` 25 // startTime: When this segment started 26 StartTime string `json:"startTime" cborgen:"startTime"` 27 Video []*Segment_Video `json:"video,omitempty" cborgen:"video,omitempty"`
··· 22 Id string `json:"id" cborgen:"id"` 23 // signingKey: The DID of the signing key used for this segment 24 SigningKey string `json:"signingKey" cborgen:"signingKey"` 25 + // size: The size of the segment in bytes 26 + Size *int64 `json:"size,omitempty" cborgen:"size,omitempty"` 27 // startTime: When this segment started 28 StartTime string `json:"startTime" cborgen:"startTime"` 29 Video []*Segment_Video `json:"video,omitempty" cborgen:"video,omitempty"`