Live video on the AT Protocol
1package media
2
3import (
4 "bytes"
5 "context"
6 "fmt"
7 "os"
8 "testing"
9 "time"
10
11 "github.com/go-gst/go-gst/gst"
12 "github.com/go-gst/go-gst/gst/pbutils"
13 "github.com/stretchr/testify/require"
14 "go.uber.org/goleak"
15 "golang.org/x/sync/errgroup"
16 "stream.place/streamplace/pkg/gstinit"
17)
18
19func TestAudioSmear(t *testing.T) {
20 gstinit.InitGST()
21 before := getLeakCount(t)
22 defer checkGStreamerLeaks(t, before)
23 ignore := goleak.IgnoreCurrent()
24 defer goleak.VerifyNone(t, ignore)
25
26 g, _ := errgroup.WithContext(context.Background())
27 for i := 0; i < streamplaceTestCount; i++ {
28 g.Go(func() error {
29 return testAudioSmearInner(t)
30 })
31 }
32 err := g.Wait()
33 require.NoError(t, err)
34}
35
36func testAudioSmearInner(t *testing.T) error {
37 uri := getFixture("duration-mismatch.mp4")
38
39 // info, err := discoverer.DiscoverURI(fmt.Sprintf("file://%s", uri))
40 // if err != nil {
41 // return err
42 // }
43
44 f, err := os.Open(uri)
45 if err != nil {
46 return err
47 }
48 defer f.Close()
49
50 // audioBs := bytes.Buffer{}
51 // videoBs := bytes.Buffer{}
52
53 seg, err := ToBuffers(context.Background(), f)
54 if err != nil {
55 return err
56 }
57
58 err = seg.Normalize(context.Background())
59 if err != nil {
60 return err
61 }
62
63 buf := bytes.Buffer{}
64 err = JoinAudioVideo(context.Background(), seg, &buf)
65 if err != nil {
66 return err
67 }
68
69 require.Equal(t, 1191255, buf.Len())
70
71 // // Write audio and video buffers to temporary files for further analysis
72 // tempDir := t.TempDir()
73
74 // audioFilePath := fmt.Sprintf("%s/audio.mp4", tempDir)
75 // videoFilePath := fmt.Sprintf("%s/video.mp4", tempDir)
76
77 // // Write audio buffer to file
78 // audioFile, err := os.Create(audioFilePath)
79 // if err != nil {
80 // return err
81 // }
82 // _, err = io.Copy(audioFile, bytes.NewReader(audioBs.Bytes()))
83 // if err != nil {
84 // return err
85 // }
86 // err = audioFile.Close()
87 // if err != nil {
88 // return err
89 // }
90
91 // // Write video buffer to file
92 // videoFile, err := os.Create(videoFilePath)
93 // if err != nil {
94 // return err
95 // }
96 // _, err = io.Copy(videoFile, bytes.NewReader(videoBs.Bytes()))
97 // if err != nil {
98 // return err
99 // }
100 // err = videoFile.Close()
101 // if err != nil {
102 // return err
103 // }
104
105 // SmearAudioTimestamps(context.Background(), bytes.NewReader(audioBs.Bytes()), &bytes.Buffer{})
106
107 // checkSame(t, videoFile.Name(), getFixture("duration-mismatch-video.mp4"))
108 // checkSame(t, audioFile.Name(), getFixture("duration-mismatch-audio.mp4"))
109 // printDiscovererInfo(info)
110 return nil
111
112}
113
114func checkSame(t *testing.T, v1, v2 string) {
115 discoverer, err := pbutils.NewDiscoverer(gst.ClockTime(time.Second * 15))
116 if err != nil {
117 panic(err)
118 }
119
120 info, err := discoverer.DiscoverURI(fmt.Sprintf("file://%s", v1))
121 require.NoError(t, err)
122 dur1 := info.GetDuration().AsDuration()
123
124 info, err = discoverer.DiscoverURI(fmt.Sprintf("file://%s", v2))
125 require.NoError(t, err)
126 dur2 := info.GetDuration().AsDuration()
127
128 require.Equal(t, *dur2, *dur1)
129}
130
131func printDiscovererInfo(info *pbutils.DiscovererInfo) {
132 fmt.Println("URI:", info.GetURI())
133 fmt.Println("Duration:", info.GetDuration())
134
135 printTags(info)
136 printStreamInfo(info.GetStreamInfo())
137
138 children := info.GetStreamList()
139 fmt.Println("Children streams:")
140 for _, child := range children {
141 printStreamInfo(child)
142 }
143}
144
145func printTags(info *pbutils.DiscovererInfo) {
146 fmt.Println("Tags:")
147 tags := info.GetTags()
148 if tags != nil {
149 fmt.Println(" ", tags)
150 return
151 }
152 fmt.Println(" no tags")
153}
154
155func printStreamInfo(info *pbutils.DiscovererStreamInfo) {
156 if info == nil {
157 return
158 }
159 fmt.Println("Stream: ")
160 fmt.Println(" Stream id:", info.GetStreamID())
161 if caps := info.GetCaps(); caps != nil {
162 fmt.Println(" Format:", caps)
163 }
164}