Live video on the AT Protocol
1package media
2
3import (
4 "bytes"
5 "context"
6 "io"
7 "os"
8 "testing"
9 "time"
10
11 "github.com/stretchr/testify/require"
12 "golang.org/x/sync/errgroup"
13)
14
15func TestMP4ToMPEGTS(t *testing.T) {
16 withNoGSTLeaks(t, func() {
17 for _, file := range []string{"sample-segment.mp4", "short-video.mp4"} {
18 // Open input file
19 inputFile, err := os.Open(getFixture(file))
20 require.NoError(t, err)
21 defer inputFile.Close()
22
23 // Create a buffer for output
24 buf := bytes.Buffer{}
25
26 bs, err := io.ReadAll(inputFile)
27 require.NoError(t, err)
28 // Create temporary output file
29
30 g, _ := errgroup.WithContext(context.Background())
31 for range streamplaceTestCount {
32 g.Go(func() error {
33 _, err := MP4ToMPEGTS(context.Background(), bytes.NewReader(bs), &buf)
34 return err
35 })
36 }
37 err = g.Wait()
38 require.NoError(t, err)
39 // Convert MPEG-TS to MP4
40
41 // Convert MP4 to MPEG-TS
42 dur, err := MP4ToMPEGTS(context.Background(), bytes.NewReader(bs), &buf)
43 require.NoError(t, err)
44 require.Greater(t, dur, int64(0), "Duration should be greater than 0")
45
46 // Verify buffer has content
47 require.Greater(t, buf.Len(), 0, "Output buffer should not be empty")
48 }
49 })
50}
51
52func TestMP4ToMPEGTSInvalid(t *testing.T) {
53 withNoGSTLeaks(t, func() {
54
55 inputFile, err := os.Open(getFixture("sample-segment.mpegts"))
56 require.NoError(t, err)
57 defer inputFile.Close()
58
59 buf := bytes.Buffer{}
60
61 bs, err := io.ReadAll(inputFile)
62 require.NoError(t, err)
63
64 // Convert MP4 to MPEG-TS
65 _, err = MP4ToMPEGTS(context.Background(), bytes.NewReader(bs), &buf)
66 require.ErrorContains(t, err, "This file is invalid and cannot be played")
67 })
68}
69
70// func TestNoRealtime(t *testing.T) {
71// gst.Init(nil)
72
73// // Open input file
74// inputFile, err := os.Open(getFixture("5sec.mp4"))
75// require.NoError(t, err)
76// defer inputFile.Close()
77
78// // Create a buffer for output
79// tsBuf := bytes.Buffer{}
80
81// // Convert MP4 to MPEG-TS
82// start := time.Now()
83// dur, err := MP4ToMPEGTS(context.Background(), inputFile, &tsBuf)
84// require.NoError(t, err)
85// require.Greater(t, dur, int64(0), "Duration should be greater than 0")
86// elapsed := time.Since(start)
87// require.Less(t, elapsed, 4*time.Second, "MP4 to MPEG-TS conversion should take less than 4 seconds")
88// require.Greater(t, tsBuf.Len(), 0, "MPEG-TS buffer should not be empty")
89
90// // Convert back to MP4
91// mp4Buf := bytes.Buffer{}
92// start = time.Now()
93// err = MPEGTSToMP4(context.Background(), bytes.NewReader(tsBuf.Bytes()), &mp4Buf)
94// require.NoError(t, err)
95// elapsed = time.Since(start)
96// require.Less(t, elapsed, 4*time.Second, "MPEG-TS to MP4 conversion should take less than 4 seconds")
97// require.Greater(t, mp4Buf.Len(), 0, "MP4 buffer should not be empty")
98// }
99
100func TestMPEGTSToMP4(t *testing.T) {
101 withNoGSTLeaks(t, func() {
102
103 // Open input file
104 inputFile, err := os.Open(getFixture("sample-segment.mpegts"))
105 require.NoError(t, err)
106 defer inputFile.Close()
107 bs, err := io.ReadAll(inputFile)
108 require.NoError(t, err)
109 // Create temporary output file
110 buf := bytes.Buffer{}
111
112 g, _ := errgroup.WithContext(context.Background())
113 for i := 0; i < streamplaceTestCount; i++ {
114 g.Go(func() error {
115 return MPEGTSToMP4(context.Background(), bytes.NewReader(bs), &buf)
116 })
117 }
118 err = g.Wait()
119 // Convert MPEG-TS to MP4
120
121 require.NoError(t, err)
122 require.Greater(t, buf.Len(), 0, "Output file should not be empty")
123 })
124}
125
126func TestMP4ToMPEGTSVideoMP4Audio(t *testing.T) {
127 withNoGSTLeaks(t, func() {
128
129 // Open input file
130 inputFile, err := os.Open(getFixture("5sec.mp4"))
131 require.NoError(t, err)
132 defer inputFile.Close()
133
134 // Create buffers for output
135 videoBuf := bytes.Buffer{}
136 audioBuf := bytes.Buffer{}
137
138 // Split MP4 into MPEG-TS video and MP4 audio
139 start := time.Now()
140 err = MP4ToMPEGTSVideoMP4Audio(context.Background(), inputFile, &videoBuf, &audioBuf)
141 require.NoError(t, err)
142 elapsed := time.Since(start)
143 require.Less(t, elapsed, 4*time.Second, "MP4 to MPEG-TS/MP4 conversion should take less than 4 seconds")
144
145 // Verify outputs
146 require.Greater(t, videoBuf.Len(), 0, "Video buffer should not be empty")
147 require.Greater(t, audioBuf.Len(), 0, "Audio buffer should not be empty")
148
149 // Join video and audio back together
150 buf := bytes.Buffer{}
151 start = time.Now()
152 err = MPEGTSVideoMP4AudioToMP4(context.Background(), &videoBuf, &audioBuf, &buf)
153 require.NoError(t, err)
154 require.Greater(t, buf.Len(), 0, "Output buffer should not be empty")
155 elapsed = time.Since(start)
156 require.Less(t, elapsed, 4*time.Second, "MPEG-TS/MP4 to MP4 conversion should take less than 4 seconds")
157 })
158}