Skip to content

Commit 580c403

Browse files
committed
issue #222: fix audio stream stutter btween ovelay TS file;
1. let continuity_counter continually between overlay ts; 2. copy audio data when transcoding ts;
1 parent 9b475d9 commit 580c403

File tree

2 files changed

+122
-2
lines changed

2 files changed

+122
-2
lines changed

platform/transcript.go

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"github.com/ossrs/go-oryx-lib/errors"
2222
ohttp "github.com/ossrs/go-oryx-lib/http"
2323
"github.com/ossrs/go-oryx-lib/logger"
24+
2425
// Use v8 because we use Go 1.16+, while v9 requires Go 1.18+
2526
"github.com/go-redis/redis/v8"
2627
"github.com/google/uuid"
@@ -1295,6 +1296,9 @@ type TranscriptSegment struct {
12951296
// Whether user clear the ASR text of this segment.
12961297
UserClearASR bool `json:"uca,omitempty"`
12971298

1299+
// The map that host the pid -> last cc
1300+
OverlayTSLastCC map[uint16]uint8 `json:"start_cc,omitempty"`
1301+
12981302
// The cost to transcode the TS file to audio file.
12991303
CostExtractAudio time.Duration `json:"eac,omitempty"`
13001304
// The cost to do ASR, converting speech to text.
@@ -1402,6 +1406,16 @@ func (v *TranscriptQueue) first() *TranscriptSegment {
14021406
return v.Segments[0]
14031407
}
14041408

1409+
func (v *TranscriptQueue) find_by(seq_no uint64) *TranscriptSegment {
1410+
for i := len(v.Segments) - 1; i >= 0; i-- {
1411+
if v.Segments[i].OverlayFile.SeqNo == seq_no {
1412+
return v.Segments[i]
1413+
}
1414+
}
1415+
1416+
return nil
1417+
}
1418+
14051419
func (v *TranscriptQueue) clearSubtitle(tsid string) error {
14061420
v.lock.Lock()
14071421
defer v.lock.Unlock()
@@ -1594,7 +1608,7 @@ func (v *TranscriptTask) OnTsSegment(ctx context.Context, msg *SrsOnHlsObject) e
15941608
func() {
15951609
// We must not update the queue, when persistence goroutine is working.
15961610
v.lock.Lock()
1597-
v.lock.Unlock()
1611+
defer v.lock.Unlock()
15981612

15991613
v.LiveQueue.enqueue(&TranscriptSegment{
16001614
Msg: msg.Msg,
@@ -1978,7 +1992,7 @@ func (v *TranscriptTask) DriveFixQueue(ctx context.Context) error {
19781992
args = append(args, strings.Fields(videoCodecParams)...)
19791993
// Generate other parameters for FFmpeg.
19801994
args = append(args, []string{
1981-
"-c:a", "aac",
1995+
"-c:a", "copy",
19821996
"-copyts", // To keep the pts not changed.
19831997
"-y", overlayFile.File,
19841998
}...)
@@ -2004,6 +2018,21 @@ func (v *TranscriptTask) DriveFixQueue(ctx context.Context) error {
20042018
}
20052019
overlayFile.Size = uint64(stats.Size())
20062020

2021+
// recaculate the continuity_counter of overlayFile
2022+
// 1. get previous segment in overlayQueue
2023+
// 2. adjust current ts segment's continuity_counter
2024+
// 2. change segment.OverlayTSLastCC
2025+
previous_ts_cc := map[uint16]uint8{}
2026+
if previous_segment := v.OverlayQueue.find_by(overlayFile.SeqNo - 1); previous_segment != nil {
2027+
previous_ts_cc = previous_segment.OverlayTSLastCC
2028+
}
2029+
2030+
if cc, err := overlayFile.AdjustCC(previous_ts_cc); err != nil {
2031+
logger.Wf(ctx, "Error when Adjust Overlay TS file %v", overlayFile.File)
2032+
} else {
2033+
segment.OverlayTSLastCC = cc
2034+
}
2035+
20072036
// Dequeue the segment from live queue and attach to asr queue.
20082037
func() {
20092038
v.lock.Lock()

platform/utils.go

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1129,6 +1129,97 @@ func (v *TsFile) String() string {
11291129
)
11301130
}
11311131

1132+
// Adjust ts packet's continuity_counter by previous ts segment.
1133+
func (v *TsFile) AdjustCC(cc map[uint16]uint8) (map[uint16]uint8, error) {
1134+
const BUF_SIZE = 188
1135+
const TS_VIDEO_AVC_PID = 256
1136+
const TS_AUDIO_AAC_PID = 257
1137+
const TS_AUDIO_MP3_PID = 258
1138+
1139+
tmp_file_name := v.File + ".tmp"
1140+
1141+
err := func() error {
1142+
file, err := os.Open(v.File)
1143+
if err != nil {
1144+
return err
1145+
}
1146+
defer file.Close()
1147+
1148+
tmp_file, err := os.Create(tmp_file_name)
1149+
if err != nil {
1150+
return err
1151+
}
1152+
defer tmp_file.Close()
1153+
1154+
buffer := make([]byte, BUF_SIZE)
1155+
1156+
for {
1157+
bytes_read, err := file.Read(buffer)
1158+
if err != nil {
1159+
if err == io.EOF {
1160+
return nil
1161+
}
1162+
1163+
return err
1164+
}
1165+
1166+
if bytes_read != BUF_SIZE {
1167+
return errors.Errorf("Read TS packet with size %v", bytes_read)
1168+
}
1169+
1170+
if sync_byte := buffer[0]; sync_byte != 0x47 {
1171+
return errors.Errorf("TS packet sync byte is not 0x47")
1172+
}
1173+
1174+
// transport_error_indicator := uint8(buffer[1] & 0x80 >> 7)
1175+
// payload_unit_start_indicator := uint8(buffer[1] & 0x40 >> 6)
1176+
// transport_priority := uint8(buffer[1] & 0x20 >> 5)
1177+
pid := uint16(buffer[1]&0x1f)<<8 + uint16(buffer[2])
1178+
// transport_scrambling_control := uint8(buffer[3] & 0xC0 >> 6)
1179+
adaptation_field_control := uint8(buffer[3] & 0x30 >> 4)
1180+
continuity_counter := uint8(buffer[3] & 0x0f)
1181+
1182+
// check whether ts packet has payload: adaptation_field_control == 01 or 11
1183+
has_payload := (adaptation_field_control & 0x01) == 1
1184+
is_AV_PID := pid == TS_VIDEO_AVC_PID || pid == TS_AUDIO_AAC_PID || pid == TS_AUDIO_MP3_PID
1185+
if has_payload && is_AV_PID {
1186+
if counter, hasKey := cc[pid]; hasKey {
1187+
if continuity_counter != counter+1 {
1188+
continuity_counter = counter + 1
1189+
if continuity_counter > 15 {
1190+
continuity_counter = 0
1191+
}
1192+
1193+
buffer[3] = (buffer[3] & 0xf0) | continuity_counter
1194+
}
1195+
1196+
cc[pid] = continuity_counter
1197+
} else {
1198+
cc[pid] = continuity_counter
1199+
}
1200+
}
1201+
1202+
if _, err := tmp_file.Write(buffer); err != nil {
1203+
return err
1204+
}
1205+
}
1206+
}()
1207+
1208+
if err != nil {
1209+
return nil, err
1210+
}
1211+
1212+
if _, err := os.Stat(tmp_file_name); err != nil {
1213+
return nil, err
1214+
}
1215+
1216+
if err := os.Rename(tmp_file_name, v.File); err != nil {
1217+
return nil, err
1218+
}
1219+
1220+
return cc, nil
1221+
}
1222+
11321223
// M3u8VoDArtifact is a HLS VoD object. Because each Dvr/Vod/RecordM3u8Stream might be DVR to many VoD file,
11331224
// each is an M3u8VoDArtifact. For example, when user publish live/livestream, there is a Dvr/Vod/RecordM3u8Stream and
11341225
// M3u8VoDArtifact, then user unpublish stream and after some seconds a VoD file is generated by M3u8VoDArtifact. Then

0 commit comments

Comments
 (0)