fork
Configure Feed
Select the types of activity you want to include in your feed.
Live video on the AT Protocol
fork
Configure Feed
Select the types of activity you want to include in your feed.
1package media
2
3import (
4 "context"
5 "fmt"
6 "io"
7 "os"
8 "sort"
9 "time"
10
11 "stream.place/streamplace/pkg/aqtime"
12 "stream.place/streamplace/pkg/config"
13 "stream.place/streamplace/pkg/localdb"
14)
15
16func ClipUser(ctx context.Context, localDB localdb.LocalDB, cli *config.CLI, user string, writer io.Writer, before *time.Time, after *time.Time) error {
17 segments, err := localDB.LatestSegmentsForUser(user, -1, false, before, after)
18 if err != nil {
19 return fmt.Errorf("unable to get segments: %w", err)
20 }
21 if len(segments) == 0 {
22 return fmt.Errorf("no segments found")
23 }
24 // Sort segments by StartTime, oldest first
25 sort.Slice(segments, func(i, j int) bool {
26 return segments[i].StartTime.Before(segments[j].StartTime)
27 })
28 segmentFiles := []io.ReadSeeker{}
29 for _, segment := range segments {
30 aqt := aqtime.FromTime(segment.StartTime)
31 fpath, err := cli.SegmentFilePath(user, fmt.Sprintf("%s.%s", aqt.FileSafeString(), "mp4"))
32 if err != nil {
33 return fmt.Errorf("unable to get segment file path: %w", err)
34 }
35 fd, err := os.Open(fpath)
36 if err != nil {
37 return fmt.Errorf("unable to open segment file: %w", err)
38 }
39 defer fd.Close()
40 segmentFiles = append(segmentFiles, fd)
41 }
42 err = CombineSegmentsUnsigned(ctx, segmentFiles, writer, false)
43 if err != nil {
44 return fmt.Errorf("unable to clip segments: %w", err)
45 }
46 return nil
47}