Skip to content

Commit e5b84b6

Browse files
committed
feat: update with ProcessingLogger adapter
1 parent 2d115d1 commit e5b84b6

18 files changed

Lines changed: 950 additions & 856 deletions

pkg/cmd/raw-recording-tool/extract_audio.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,18 @@ func runExtractAudio(cmd *cobra.Command, args []string) error {
9595
}
9696

9797
// Extract audio tracks
98-
if err := processing.ExtractTracks(globalArgs.WorkDir, globalArgs.Output, userID, sessionID, trackID, metadata, "audio", "both", fillGaps, fixDtx, logger); err != nil {
98+
extractor := processing.NewTrackExtractor(logger)
99+
if _, err := extractor.ExtractTracks(&processing.TrackExtractorConfig{
100+
WorkDir: globalArgs.WorkDir,
101+
OutputDir: globalArgs.Output,
102+
UserID: userID,
103+
SessionID: sessionID,
104+
TrackID: trackID,
105+
TrackKind: TrackTypeAudio,
106+
MediaType: "both",
107+
FillGap: fillGaps,
108+
FillDtx: fixDtx,
109+
}, metadata); err != nil {
99110
return fmt.Errorf("failed to extract audio: %w", err)
100111
}
101112

pkg/cmd/raw-recording-tool/extract_video.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,18 @@ func runExtractVideo(cmd *cobra.Command, args []string) error {
9393
}
9494

9595
// Extract video tracks
96-
if err := processing.ExtractTracks(globalArgs.WorkDir, globalArgs.Output, userID, sessionID, trackID, metadata, "video", "both", fillGaps, false, logger); err != nil {
96+
extractor := processing.NewTrackExtractor(logger)
97+
if _, err := extractor.ExtractTracks(&processing.TrackExtractorConfig{
98+
WorkDir: globalArgs.WorkDir,
99+
OutputDir: globalArgs.Output,
100+
UserID: userID,
101+
SessionID: sessionID,
102+
TrackID: trackID,
103+
TrackKind: TrackTypeVideo,
104+
MediaType: "both",
105+
FillGap: fillGaps,
106+
FillDtx: false,
107+
}, metadata); err != nil {
97108
return fmt.Errorf("failed to extract video tracks: %w", err)
98109
}
99110

pkg/cmd/raw-recording-tool/mix_audio.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ func runMixAudio(cmd *cobra.Command, args []string) error {
7474
WithScreenshare: false,
7575
WithExtract: true,
7676
WithCleanup: false,
77-
}, metadata, logger)
77+
}, metadata)
7878

7979
logger.Info("Mix-audio command completed successfully")
8080
return nil

pkg/cmd/raw-recording-tool/mux_av.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,16 +119,16 @@ func runMuxAV(cmd *cobra.Command, args []string) error {
119119

120120
// Mux audio/video tracks
121121
muxer := processing.NewAudioVideoMuxer(logger)
122-
if err := muxer.MuxAudioVideoTracks(&processing.AudioVideoMuxerConfig{
122+
if _, err := muxer.MuxAudioVideoTracks(&processing.AudioVideoMuxerConfig{
123123
WorkDir: globalArgs.WorkDir,
124124
OutputDir: globalArgs.Output,
125125
UserID: userID,
126126
SessionID: sessionID,
127127
TrackID: trackID,
128-
Media: media,
128+
MediaType: media,
129129
WithExtract: true,
130130
WithCleanup: false,
131-
}, metadata, logger); err != nil {
131+
}, metadata); err != nil {
132132
return fmt.Errorf("failed to mux audio/video tracks: %w", err)
133133
}
134134

pkg/cmd/raw-recording-tool/process_all.go

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -110,12 +110,33 @@ func runProcessAll(cmd *cobra.Command, args []string) error {
110110
}
111111

112112
// Extract audio tracks
113-
if err := processing.ExtractTracks(globalArgs.WorkDir, globalArgs.Output, "", "", "", metadata, "audio", "both", true, true, logger); err != nil {
113+
extractor := processing.NewTrackExtractor(logger)
114+
if _, err := extractor.ExtractTracks(&processing.TrackExtractorConfig{
115+
WorkDir: globalArgs.WorkDir,
116+
OutputDir: globalArgs.Output,
117+
UserID: "",
118+
SessionID: "",
119+
TrackID: "",
120+
TrackKind: TrackTypeAudio,
121+
MediaType: "both",
122+
FillGap: true,
123+
FillDtx: true,
124+
}, metadata); err != nil {
114125
return fmt.Errorf("failed to extract audio tracks: %w", err)
115126
}
116127

117128
// Extract video tracks
118-
if err := processing.ExtractTracks(globalArgs.WorkDir, globalArgs.Output, "", "", "", metadata, "video", "both", true, true, logger); err != nil {
129+
if _, err := extractor.ExtractTracks(&processing.TrackExtractorConfig{
130+
WorkDir: globalArgs.WorkDir,
131+
OutputDir: globalArgs.Output,
132+
UserID: "",
133+
SessionID: "",
134+
TrackID: "",
135+
TrackKind: TrackTypeVideo,
136+
MediaType: "both",
137+
FillGap: true,
138+
FillDtx: true,
139+
}, metadata); err != nil {
119140
return fmt.Errorf("failed to extract video tracks: %w", err)
120141
}
121142

@@ -127,20 +148,20 @@ func runProcessAll(cmd *cobra.Command, args []string) error {
127148
WithScreenshare: false,
128149
WithExtract: false,
129150
WithCleanup: false,
130-
}, metadata, logger)
151+
}, metadata)
131152

132153
// Mux audio/video tracks
133154
muxer := processing.NewAudioVideoMuxer(logger)
134-
if err := muxer.MuxAudioVideoTracks(&processing.AudioVideoMuxerConfig{
155+
if _, err := muxer.MuxAudioVideoTracks(&processing.AudioVideoMuxerConfig{
135156
WorkDir: globalArgs.WorkDir,
136157
OutputDir: globalArgs.Output,
137158
UserID: "",
138159
SessionID: "",
139160
TrackID: "",
140-
Media: "",
161+
MediaType: "",
141162
WithExtract: false,
142163
WithCleanup: false,
143-
}, metadata, logger); err != nil {
164+
}, metadata); err != nil {
144165
return fmt.Errorf("failed to mux audio/video tracks: %w", err)
145166
}
146167

pkg/cmd/raw-recording-tool/processing/archive_input.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,11 @@ import (
88
"os"
99
"path/filepath"
1010
"strings"
11-
12-
"github.com/GetStream/getstream-go/v3"
1311
)
1412

1513
// extractToTempDir extracts archive to temp directory or returns the directory path
1614
// Returns: (workingDir, cleanupFunc, error)
17-
func ExtractToTempDir(inputPath string, logger *getstream.DefaultLogger) (string, func(), error) {
15+
func ExtractToTempDir(inputPath string, logger *ProcessingLogger) (string, func(), error) {
1816
// If it's already a directory, just return it
1917
if stat, err := os.Stat(inputPath); err == nil && stat.IsDir() {
2018
logger.Debug("Input is already a directory: %s", inputPath)
@@ -48,7 +46,7 @@ func ExtractToTempDir(inputPath string, logger *getstream.DefaultLogger) (string
4846
}
4947

5048
// extractTarGzToDir extracts a tar.gz file to the specified directory
51-
func extractTarGzToDir(tarGzPath, destDir string, logger *getstream.DefaultLogger) error {
49+
func extractTarGzToDir(tarGzPath, destDir string, logger *ProcessingLogger) error {
5250
file, err := os.Open(tarGzPath)
5351
if err != nil {
5452
return fmt.Errorf("failed to open tar.gz file: %w", err)

pkg/cmd/raw-recording-tool/processing/archive_json.go

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
package processing
22

3+
import "time"
4+
35
type SessionTimingMetadata struct {
4-
ParticipantID string `json:"participant_id"`
5-
UserSessionID string `json:"user_session_id"`
6+
CallType string `json:"call_type"`
7+
CallID string `json:"call_id"`
8+
CallSessionID string `json:"call_session_id"`
9+
CallStartTime time.Time `json:"call_start_time"`
10+
ParticipantID string `json:"participant_id"`
11+
UserSessionID string `json:"user_session_id"`
612
Segments struct {
713
Audio []*SegmentMetadata `json:"audio"`
814
Video []*SegmentMetadata `json:"video"`
@@ -27,4 +33,12 @@ type SegmentMetadata struct {
2733
FirstRtcpNtpTimestamp int64 `json:"first_rtcp_ntp_timestamp,omitempty"`
2834
LastRtcpRtpTimestamp uint32 `json:"last_rtcp_rtp_timestamp,omitempty"`
2935
LastRtcpNtpTimestamp int64 `json:"last_rtcp_ntp_timestamp,omitempty"`
36+
37+
FirstKeyFrameOffsetMs *int64 `json:"first_key_frame_offset_ms,omitempty"`
38+
MaxFrameDimension *SegmentFrameDimension `json:"max_frame_dimension,omitempty"`
39+
}
40+
41+
type SegmentFrameDimension struct {
42+
Width uint32 `json:"width,omitempty"`
43+
Height uint32 `json:"height,omitempty"`
3044
}

pkg/cmd/raw-recording-tool/processing/archive_metadata.go

Lines changed: 60 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,28 @@ import (
1010
"path/filepath"
1111
"sort"
1212
"strings"
13-
14-
"github.com/GetStream/getstream-go/v3"
13+
"time"
1514
)
1615

1716
// TrackInfo represents a single track with its metadata (deduplicated across segments)
1817
type TrackInfo struct {
19-
UserID string `json:"userId"` // participant_id from timing metadata
20-
SessionID string `json:"sessionId"` // user_session_id from timing metadata
21-
TrackID string `json:"trackId"` // track_id from segment
22-
TrackType string `json:"trackType"` // "audio" or "video" (cleaned from TRACK_TYPE_*)
23-
IsScreenshare bool `json:"isScreenshare"` // true if this is a screenshare track
24-
Codec string `json:"codec"` // codec info
25-
SegmentCount int `json:"segmentCount"` // number of segments for this track
26-
Segments []*SegmentInfo `json:"segments"` // list of filenames (for JSON output only)
27-
28-
ConcatenatedContainerPath string
18+
CallType string `json:"callType"` // call_type from timing metadata
19+
CallID string `json:"callId"` // call_id from timing metadata
20+
CallSessionID string `json:"callSessionId"` // call_session_id from timing metadata
21+
CallStartTime time.Time `json:"callStartTime"` // call_start_time from timing metadata
22+
UserID string `json:"userId"` // participant_id from timing metadata
23+
SessionID string `json:"sessionId"` // user_session_id from timing metadata
24+
TrackID string `json:"trackId"` // track_id from segment
25+
TrackType string `json:"trackType"` // track_type from segment
26+
TrackKind string `json:"trackKind"` // "audio" or "video" (cleaned from TRACK_TYPE_*)
27+
IsScreenshare bool `json:"isScreenshare"` // true if this is a screenshare track
28+
Codec string `json:"codec"` // codec info
29+
SegmentCount int `json:"segmentCount"` // number of segments for this track
30+
TrackStartTime time.Time `json:"trackStartTime"` // first_rtp_unix_timestamp from segment
31+
TrackEndTime time.Time `json:"trackEndTime"` // last_rtp_unix_timestamp from segment
32+
Segments []*SegmentInfo `json:"segments"` // list of filenames (for JSON output only)
33+
34+
ConcatenatedTrackFileInfo *TrackFileInfo
2935
}
3036

3137
type SegmentInfo struct {
@@ -35,7 +41,13 @@ type SegmentInfo struct {
3541
SdpPath string
3642
ContainerPath string
3743
ContainerExt string
38-
FFMpegOffset int64
44+
}
45+
46+
type TrackFileInfo struct {
47+
Name string
48+
StartAt time.Time
49+
EndAt time.Time
50+
MaxFrameDimension SegmentFrameDimension
3951
}
4052

4153
// RecordingMetadata contains all tracks and session information
@@ -47,11 +59,11 @@ type RecordingMetadata struct {
4759

4860
// MetadataParser handles parsing of raw recording files
4961
type MetadataParser struct {
50-
logger *getstream.DefaultLogger
62+
logger *ProcessingLogger
5163
}
5264

5365
// NewMetadataParser creates a new metadata parser
54-
func NewMetadataParser(logger *getstream.DefaultLogger) *MetadataParser {
66+
func NewMetadataParser(logger *ProcessingLogger) *MetadataParser {
5567
return &MetadataParser{
5668
logger: logger,
5769
}
@@ -197,27 +209,42 @@ func (p *MetadataParser) parseTimingMetadataFile(data []byte) ([]*TrackInfo, err
197209
// Use a map to deduplicate tracks by unique key
198210
trackMap := make(map[string]*TrackInfo)
199211

200-
processSegment := func(segment *SegmentMetadata, trackType string) {
212+
processSegment := func(segment *SegmentMetadata, trackKind string) {
201213
key := fmt.Sprintf("%s|%s|%s|%s",
202214
sessionMetadata.ParticipantID,
203215
sessionMetadata.UserSessionID,
204216
segment.TrackID,
205-
trackType)
217+
trackKind)
206218

207219
if existingTrack, exists := trackMap[key]; exists {
208220
existingTrack.Segments = append(existingTrack.Segments, &SegmentInfo{metadata: segment})
209221
existingTrack.SegmentCount++
222+
223+
ts, te := time.UnixMilli(segment.FirstRtpUnixTimestamp), time.UnixMilli(segment.LastRtpUnixTimestamp)
224+
if ts.Before(existingTrack.TrackStartTime) {
225+
existingTrack.TrackStartTime = ts
226+
}
227+
if te.After(existingTrack.TrackEndTime) {
228+
existingTrack.TrackEndTime = te
229+
}
210230
} else {
211231
// Create new track
212232
track := &TrackInfo{
213-
UserID: sessionMetadata.ParticipantID,
214-
SessionID: sessionMetadata.UserSessionID,
215-
TrackID: segment.TrackID,
216-
TrackType: p.cleanTrackType(segment.TrackType),
217-
IsScreenshare: p.isScreenshareTrack(segment.TrackType),
218-
Codec: segment.Codec,
219-
SegmentCount: 1,
220-
Segments: []*SegmentInfo{{metadata: segment}},
233+
CallType: sessionMetadata.CallType,
234+
CallID: sessionMetadata.CallID,
235+
CallSessionID: sessionMetadata.CallSessionID,
236+
CallStartTime: sessionMetadata.CallStartTime,
237+
UserID: sessionMetadata.ParticipantID,
238+
SessionID: sessionMetadata.UserSessionID,
239+
TrackID: segment.TrackID,
240+
TrackType: segment.TrackType,
241+
TrackKind: p.cleanTrackType(segment.TrackType),
242+
IsScreenshare: p.isScreenshareTrack(segment.TrackType),
243+
Codec: segment.Codec,
244+
SegmentCount: 1,
245+
TrackStartTime: time.UnixMilli(segment.FirstRtpUnixTimestamp),
246+
TrackEndTime: time.UnixMilli(segment.LastRtpUnixTimestamp),
247+
Segments: []*SegmentInfo{{metadata: segment}},
221248
}
222249
trackMap[key] = track
223250
}
@@ -254,9 +281,9 @@ func (p *MetadataParser) isScreenshareTrack(trackType string) bool {
254281
func (p *MetadataParser) cleanTrackType(trackType string) string {
255282
switch trackType {
256283
case "TRACK_TYPE_AUDIO", "TRACK_TYPE_SCREEN_SHARE_AUDIO":
257-
return "audio"
284+
return trackKindAudio
258285
case "TRACK_TYPE_VIDEO", "TRACK_TYPE_SCREEN_SHARE":
259-
return "video"
286+
return trackKindVideo
260287
default:
261288
return strings.ToLower(trackType)
262289
}
@@ -298,20 +325,20 @@ func (p *MetadataParser) extractUniqueSessions(tracks []*TrackInfo) []string {
298325
// Only one filter (userID, sessionID, or trackID) can be specified at a time
299326
// Empty values are ignored, specific values must match
300327
// If all are empty, all tracks are returned
301-
func FilterTracks(tracks []*TrackInfo, userID, sessionID, trackID, trackType, mediaFilter string) []*TrackInfo {
328+
func FilterTracks(tracks []*TrackInfo, userID, sessionID, trackID, trackKind, mediaType string) []*TrackInfo {
302329
filtered := make([]*TrackInfo, 0)
303330

304331
for _, track := range tracks {
305-
if trackType != "" && track.TrackType != trackType {
306-
continue // Skip tracks with wrong TrackType
332+
if trackKind != "" && track.TrackKind != trackKind {
333+
continue // Skip tracks with wrong trackKind
307334
}
308335

309336
// Apply media type filtering if specified
310-
if mediaFilter != "" && mediaFilter != "both" {
311-
if mediaFilter == "user" && track.IsScreenshare {
337+
if mediaType != "" && mediaType != mediaTypeBoth {
338+
if mediaType == mediaTypeUser && track.IsScreenshare {
312339
continue // Skip display tracks when only user requested
313340
}
314-
if mediaFilter == "display" && !track.IsScreenshare {
341+
if mediaType == mediaTypeDisplay && !track.IsScreenshare {
315342
continue // Skip user tracks when only display requested
316343
}
317344
}

0 commit comments

Comments
 (0)