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