Comments (19)
I don't see why not.
I currently use video iframes to split segments,
let me see what I can work out for audio.
Adrian
from x9k3.
I had no problem doing it, let me know if this works for you.
- I made an audio only ts file
ffmpeg -copyts -i video.ts -vn -c copy audio.ts
a@debian:~/build/x9k3$ ffprobe -hide_banner audio.ts
Input #0, mpegts, from 'audio.ts':
Duration: 00:48:04.10, start: 4.220300, bitrate: 159 kb/s
Program 1
Metadata:
service_name : Service01
service_provider: FFmpeg
Stream #0:0[0x100](und): Audio: aac (LC) ([15][0][0][0] / 0x000F), 44100 Hz, stereo, fltp, 108 kb/s
- I made a sidecar file of PTS, SCTE35 Cue pairs
a@debian:~/build/x9k3$ cat sidecar.txt
102.805,/DAlAAAAAAAAAP/wFAUAAAABf+/+AJKsov4ADdtEAAEAAAAA7eV+Kg==
177.6,/DAlAAAAAAAAAP/wFAUAAAACf+/+APljwP4ADdtEAAIAAAAACcxDcg====
411.0,/DAlAAAAAAAAAP/wFAUAAAADf+/+AjnqcP4ADdtEAAMAAAAASnrfIQ====
927.697,/DAlAAAAAAAAAP/wFAUAAAAEf+/+BP99uv4ADdtEAAQAAAAAtZKbsQ==
1286.52,/DAlAAAAAAAAAP/wFAUAAAAFf+/+BuxCcP4ADdtEAAUAAAAAxSzhag==
2190.39,/DAlAAAAAAAAAP/wFAUAAAAGf+/+C8WJPP4ADdtEAAYAAAAAM8x/Xw==
2807.71,/DAlAAAAAAAAAP/wFAUAAAAHf+/+DxVLzP4ADdtEAAcAAAAAljzkJg==
2891.63,/DAlAAAAAAAAAP/wFAUAAAAIf+/+D4iK7P4ADdtEAAgAAAAAR8yZag==
- x9k3
x9k3 -i audio.ts -s sidecar.txt
- check for cues in the m3u8
a@debian:~/build/x9k3$ grep -1 CUE-OUT=YES index.m3u8
# Splice Point @ 106.805
#EXT-X-SCTE35:CUE="/DAlAAAAAAAAAP/wFAUAAAABf+/+AJKsov4ADdtEAAEAAAAA7eV+Kg==",CUE-OUT=YES
#EXTINF:2.0898,
--
# Splice Point @ 181.6
#EXT-X-SCTE35:CUE="/DAlAAAAAAAAAP/wFAUAAAACf+/+APljwP4ADdtEAAIAAAAACcxDcg==",CUE-OUT=YES
#EXTINF:2.136233,
--
# Splice Point @ 415.0
#EXT-X-SCTE35:CUE="/DAlAAAAAAAAAP/wFAUAAAADf+/+AjnqcP4ADdtEAAMAAAAASnrfIQ==",CUE-OUT=YES
#EXTINF:2.159455,
--
# Splice Point @ 931.697
#EXT-X-SCTE35:CUE="/DAlAAAAAAAAAP/wFAUAAAAEf+/+BP99uv4ADdtEAAQAAAAAtZKbsQ==",CUE-OUT=YES
#EXTINF:2.112989,
--
# Splice Point @ 1290.52
#EXT-X-SCTE35:CUE="/DAlAAAAAAAAAP/wFAUAAAAFf+/+BuxCcP4ADdtEAAUAAAAAxSzhag==",CUE-OUT=YES
#EXTINF:2.136234,
--
# Splice Point @ 2194.39
#EXT-X-SCTE35:CUE="/DAlAAAAAAAAAP/wFAUAAAAGf+/+C8WJPP4ADdtEAAYAAAAAM8x/Xw==",CUE-OUT=YES
#EXTINF:2.136256,
--
# Splice Point @ 2811.71
#EXT-X-SCTE35:CUE="/DAlAAAAAAAAAP/wFAUAAAAHf+/+DxVLzP4ADdtEAAcAAAAAljzkJg==",CUE-OUT=YES
#EXTINF:2.020144,
- tested in ffplay
ffplay index.m3u8
from x9k3.
This should help,
https://github.com/futzu/scte35-threefive/blob/master/Encoding.md
let me know if you have any questions.
from x9k3.
pip3 install --upgrade x9k3
from x9k3.
Will try this and come back (have to dev first the sidecar generator using live not file -extract PTS and auto use that to generate sidecar)
from x9k3.
This is what I use to generate splice inserts.
from threefive import Cue,SpliceInsert
def mk_cue(event_id, pts, duration=None):
"""
mk_cue make a SCTE-35 Cue
with a Splice Insert command.
set duration to make a CUE-OUT,
"""
pts= float(pts)
cue = Cue()
# default is a CUE-IN
sin = SpliceInsert()
sin.splice_event_id = event_id
sin.splice_event_cancel_indicator = False
sin.out_of_network_indicator = False
sin.time_specified_flag = False
sin.program_splice_flag = True
sin.duration_flag = False
sin.splice_immediate_flag = True
sin.unique_program_id = event_id
sin.avail_num = 0
sin.avail_expected = 0
# If we have a duration, make a CUE-OUT
if duration is not None:
sin.time_specified_flag = True
sin.time_specified_flag = True
sin.break_duration = float(duration)
sin.break_auto_return = True
sin.break_duration = duration
sin.splice_immediate_flag = False
sin.duration_flag = True
sin.out_of_network_indicator = True
sin.pts_time = pts
cue.command = sin # Add SpliceInsert to the SCTE35 cue
cue_string = cue.encode() # Use cue.encode_as_hex() for hex instead of base64
cue.decode()
return pts,cue_string
from x9k3.
This will be in the next threefive release,
you can use it now.
"""
encode.py
threefive.encode has helper functions for Cue encoding.
"""
from threefive.commands import SpliceNull, SpliceInsert, TimeSignal
from threefive.cue import Cue
def mk_splice_null():
"""
mk_splice_null returns a Cue
with a Splice Null
"""
cue = Cue()
sn = SpliceNull()
cue.command = sn
cue.encode()
return cue
def mk_time_signal(pts=None):
"""
mk_time_signal returns a Cue
with a Time Signal
if pts is NOT set:
time_specified_flag False
if pts IS set:
time_specified_flag True
pts_time pts
"""
cue = Cue()
ts = TimeSignal()
ts.time_specified_flag = False
if pts:
pts = float(pts)
ts.time_specified_flag = True
ts.pts_time = pts
cue.command = ts
cue.encode()
return cue
def mk_splice_insert(event_id, pts, duration=None):
"""
mk_cue returns a Cue
with a Splice Insert.
splice_event_id = event_id
If duration is NOT set,
out_of_network_indicator False
time_specified_flag False
duration_flag False
splice_immediate_flag True
if duration IS set:
out_of_network_indicator True
time_specified_flag True
duration_flag True
splice_immediate_flag False
break_auto_return True
break_duration duration
pts_time pts
"""
pts = float(pts)
cue = Cue()
# default is a CUE-IN
sin = SpliceInsert()
sin.splice_event_id = event_id
sin.splice_event_cancel_indicator = False
sin.out_of_network_indicator = False
sin.time_specified_flag = False
sin.program_splice_flag = True
sin.duration_flag = False
sin.splice_immediate_flag = True
sin.unique_program_id = event_id
sin.avail_num = 0
sin.avail_expected = 0
# If we have a duration, make a CUE-OUT
if duration is not None:
duration = float(duration)
sin.time_specified_flag = True
sin.break_duration = duration
sin.break_auto_return = True
sin.splice_immediate_flag = False
sin.duration_flag = True
sin.out_of_network_indicator = True
sin.pts_time = pts
cue.command = sin # Add SpliceInsert to the SCTE35 cue
cue.encode()
return cue
from x9k3.
One more thing I'm searching for (I'm still working on this):
-get combination of PTS (could be begining of first segment for each m3u8) and PROGRAM-DATE-TIME. Even if written to console.
-written EXT-X-PROGRAM-DATE-TIME for live streams
#EXT-X-PROGRAM-DATE-TIME:2022-10-11T18:46:47.257Z
-CUE-OUT-CONT currentTime/totalDuration for segments in the middle of cue-out/ cut-in
from x9k3.
I have to say, #EXT-X-PROGRAM-DATE-TIME makes no sense to me. If it's a "live" stream wouldn't the time be the current time?
- x9k4.py
import datetime
from x9k3 import X9K3
class X9K4(X9K3):
"""
X9K4 is X9K3 with #EXT-X-PROGRAM-DATE-TIME
"""
def _write_segment(self):
"""
_write_segment creates segment file,
writes segment meta data to self.active_data
"""
if not self.start:
return
seg_file = f"seg{self.seg.seg_num}.ts"
self.seg.seg_uri = self.mk_uri(self.output_dir, seg_file)
if self.seg.seg_stop:
self.seg.seg_time = round(self.seg.seg_stop - self.seg.seg_start, 6)
if self.live:
self.cue_out_continue()
#PTS
self.active_data.write(f'# PTS {round(self.seg.seg_start, 6)}\n')
# EXT-X-PROGRAM-DATE-TIME
iso8601 = f"{datetime.datetime.utcnow().isoformat()}Z"
pdt = f"#EXT-X-PROGRAM-DATE-TIME:{iso8601}"
self.active_data.write(pdt + "\n")
if self.scte35.cue_tag:
self.active_data.write(self.scte35.cue_tag + "\n")
self.scte35.cue_tag = None
with open(self.seg.seg_uri, "wb+") as a_seg:
a_seg.write(self.active_segment.getbuffer())
a_seg.flush()
del self.active_segment
self.active_data.write(f"#EXTINF:{self.seg.seg_time},\n")
self.active_data.write(seg_file + "\n")
self.seg.seg_start = self.seg.seg_stop
self.seg.seg_stop += self.seconds
self.window.append(
(self.seg.seg_num, self.seg.seg_uri, self.active_data.getvalue())
)
self.seg.seg_num += 1
if __name__ == "__main__":
x9k = X9K4()
x9k.run()
- Output
# PTS 21.286556
#EXT-X-PROGRAM-DATE-TIME:2022-10-12T01:47:06.666295Z
#EXTINF:2.002,
seg9.ts
from x9k3.
I'm redoing the tag stuff. It will solve the CONT issues. Probably less than a week for me to finish it,
from x9k3.
Are you good on this? I'm going to close it if you are, let me know.
from x9k3.
Yes, also HLS tag option was a great addition. Will reopen another issue as I move forward.
Just regarding #EXT-X-PROGRAM-DATE-TIME - I still believe it is useful for live. If for live stream you know that it has to CUE-OUT on example 06:00:00.000AM you can calculate where this is when you combine PROGRAM-DATE-TIME and segment duration to get correct PTS. Without PROGRAM-DATE-TIME you don't know what delay it took in encoding and have no reference to real clock.
from x9k3.
Regarding CUE-IN and #EXT-X-DISCONTINUITY tag. As I see example below, #EXT-X-DISCONTINUITY should be on next segment after break not last segment of ad-break. I'm working on live stream not VOD.
using x9ks latest from pip (0.1.45):
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:3
#EXT-X-MEDIA-SEQUENCE:1566
#PTS 3453.421333
#EXTINF:2.0,
seg1566.ts
#EXT-X-DISCONTINUITY
# Splice Point @ 3456.421333
#EXT-X-CUE-OUT:6.0
#PTS 3457.454667
#EXTINF:3.966666,
seg1567.ts
#EXT-X-DISCONTINUITY
# Splice Point @ 3462.421333
#EXT-X-CUE-IN
#PTS 3463.454667
#EXTINF:3.966666,
seg1568.ts
#PTS 3467.421333
#EXTINF:2.0,
https://stackoverflow.com/questions/47047919/how-does-ext-x-discontinuity-sequence-tag-work-in-hls-m3u8-file
https://developer.apple.com/documentation/http_live_streaming/example_playlists_for_http_live_streaming/incorporating_ads_into_a_playlist example:
#EXTM3U
#EXT-X-TARGETDURATION:10
#EXT-X-VERSION:4
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:10.0,
ad0.ts
#EXTINF:8.0,
ad1.ts
#EXT-X-DISCONTINUITY
#EXTINF:10.0,
movieA.ts
#EXTINF:10.0,
movieB.ts
Maybe it makes no reason to add discontinuity in x9k3, since discontinuity is needed only if CUE-OUT is actually used (not skipped). In that case application replacing content can also update (add) #EXT-X-DISCONTINUITY.
Are automatic returns (CUE-IN) after CUE-OUT duration supported. At the moment when we add CUE-OUT but no CUE-IN to sidecar -> cue-out-cont will go over cue-out duration. Maybe just add some warning in console if SCTE-35 has "break_auto_return": true, that auto_return will not run.
#EXT-X-TARGETDURATION:3
#EXT-X-MEDIA-SEQUENCE:1876
#EXT-X-CUE-OUT-CONT:11.966666/6.0
#PTS 4941.421333
#EXTINF:2.0,
seg1876.ts
#EXT-X-CUE-OUT-CONT:13.966666/6.0
#PTS 4943.421333
#EXTINF:2.0,
seg1877.ts
#EXT-X-CUE-OUT-CONT:15.966666/6.0
#PTS 4945.421333
used scte-35
{
"info_section": {
"table_id": "0xfc",
"section_syntax_indicator": false,
"private": false,
"sap_type": "0x3",
"sap_details": "No Sap Type",
"section_length": 47,
"protocol_version": 0,
"encrypted_packet": false,
"encryption_algorithm": 0,
"pts_adjustment_ticks": 0,
"pts_adjustment": 0.0,
"cw_index": "0x0",
"tier": "0xfff",
"splice_command_length": 20,
"splice_command_type": 5,
"descriptor_loop_length": 10,
"crc": "0x14e4df6a"
},
"command": {
"command_length": 20,
"command_type": 5,
"name": "Splice Insert",
"time_specified_flag": true,
"pts_time": 5070.421333,
"pts_time_ticks": 456337920,
"break_auto_return": true,
"break_duration": 6.0,
"break_duration_ticks": 540000,
"splice_event_id": 19,
"splice_event_cancel_indicator": false,
"out_of_network_indicator": true,
"program_splice_flag": true,
"duration_flag": true,
"splice_immediate_flag": false,
"unique_program_id": 2,
"avail_num": 0,
"avail_expected": 0
},
"descriptors": [
{
"tag": 0,
"descriptor_length": 8,
"name": "Avail Descriptor",
"identifier": "CUEI",
"provider_avail_id": 0
}
]
}
from x9k3.
'Regarding CUE-IN and #EXT-X-DISCONTINUITY tag. As I see example below, #EXT-X-DISCONTINUITY should be on next segment after break not last segment of ad-break. I'm working on live stream not VOD.'
Damn it, I meant to fix that, I saw that too.
from x9k3.
'Are automatic returns (CUE-IN) after CUE-OUT duration supported. At the moment when we add CUE-OUT but no CUE-IN to sidecar -> cue-out-cont will go over cue-out duration. Maybe just add some warning in console if SCTE-35 has "break_auto_return": true, that auto_return will not run.'
Yeah, I see what you're saying,
I agree that needs to be fixed, but it probably wont be anytime soon.
I showed you how to add the #EXT-X-PROGRAM-DATE-TIME and PTS if you want it,
you might want to look at the stream_diff in the output.
./seg3.ts start: 8.868422 duration: 2.002000 stream diff: 1.950796
Stream diff is the difference between real time playback and segment generation.
The stream diff above means that the last segment was generated 1.950796 seconds ahead of real time playback,
As long as the stream diff stays between -2 and +2, the stream should play without error.
90% of the time, x9k3 is sleeping to slow itself down to keep the sliding window in sync.
I cannot assume that an application will add a DISCONTINUITY and if it's not in place the stream tends to break.
Look, you make a lot of valid points, but I just don't have time to implement all the features you want,
if you want to hire me, I can get on it next week, if not, it won't be any time soon. I am just being honest with you.
from x9k3.
I fully understand your point of view. My ideas are mostly brainstorming after I'm working around using TS splicing in x9k3 for a few days. Hope more users come to use and find x9k3 useful! Maybe just add license header to source files since I see you already declared MIT license on PIP (https://pypi.org/).
from x9k3.
I think I finally fixed the CUE-IN DISCONTINUITY bug.
from x9k3.
pypy3 -mpip install --upgrade x9k3
a@debian:~/build/x9k3$ pypy3 x9k3 -h
usage: x9k3.py [-h] [-i INPUT] [-o OUTPUT_DIR] [-s SIDECAR] [-t TIME]
[-T HLS_TAG] [-w WINDOW_SIZE] [-d] [-l] [-r] [-v] [-p]
optional arguments:
-h, --help show this help message and exit
-i INPUT, --input INPUT
Input source, like "/home/a/vid.ts" or
"udp://@235.35.3.5:3535" or "https://futzu.com/xaa.ts"
-o OUTPUT_DIR, --output_dir OUTPUT_DIR
Directory for segments and index.m3u8 ( created if it
does not exist )
-s SIDECAR, --sidecar SIDECAR
Sidecar file of scte35 cues. each line contains PTS,
Cue
-t TIME, --time TIME Segment time in seconds ( default is 2)
-T HLS_TAG, --hls_tag HLS_TAG
x_scte35, x_cue, x_daterange, or x_splicepoint
(default x_cue)
-w WINDOW_SIZE, --window_size WINDOW_SIZE
sliding window size(default:5)
-d, --delete delete segments ( enables --live )
-l, --live Flag for a live event ( enables sliding window m3u8 )
-r, --replay Flag for replay (looping) ( enables --live and
--delete )
-v, --version Show version
- New !
-p, --program_date_time
Flag to add Program Date Time tags to index.m3u8 (
enables --live)
from x9k3.
I think I finally fixed the CUE-IN DISCONTINUITY bug.
I'm afraid that #EXT-X-DISCONTINUITY is still 1 segment too fast (I'm running on v.0.1.59). As I understand it should be on seg4967.ts and not on seg4966.ts.
I'm running in HLS LIVE mode with cue-out and cue-in signals sent to sidecar.
current version:
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:3
#EXT-X-MEDIA-SEQUENCE:4963
#EXT-X-DISCONTINUITY-SEQUENCE:702
# Splice Point @ 10448.823856
#EXT-X-DISCONTINUITY
#Iframe @ 10448.823856
#EXT-X-PROGRAM-DATE-TIME:2022-10-27T17:59:21.292480Z
#EXT-X-SCTE35:CUE="/DAvAAAAAAAAAP/wFAUAAAGPf+/+OAt8Yf4ACD1gAAIAAAAKAAhDVUVJAAAAAOynsiA=" ,CUE-OUT=YES
#EXTINF:2.090,
seg4963.ts
#Iframe @ 10451.099411
#EXT-X-PROGRAM-DATE-TIME:2022-10-27T17:59:23.590936Z
#EXT-X-SCTE35:CUE="/DAvAAAAAAAAAP/wFAUAAAGPf+/+OAt8Yf4ACD1gAAIAAAAKAAhDVUVJAAAAAOynsiA=" ,CUE-OUT=CONT
#EXTINF:2.067,
seg4964.ts
#Iframe @ 10453.142767
#EXT-X-PROGRAM-DATE-TIME:2022-10-27T17:59:25.594458Z
#EXT-X-SCTE35:CUE="/DAvAAAAAAAAAP/wFAUAAAGPf+/+OAt8Yf4ACD1gAAIAAAAKAAhDVUVJAAAAAOynsiA=" ,CUE-OUT=CONT
#EXTINF:2.043,
seg4965.ts
# Splice Point @ 10455.186122
#EXT-X-DISCONTINUITY
#Iframe @ 10455.186122
#EXT-X-PROGRAM-DATE-TIME:2022-10-27T17:59:27.637347Z
#EXT-X-SCTE35:CUE="/DAqAAAAAAAAAP/wDwUAAAGPf0/+OBO5wQACAAAACgAIQ1VFSQAAAADsueIZ" ,CUE-IN=YES
#EXTINF:2.043,
seg4966.ts
#Iframe @ 10457.4849
#EXT-X-PROGRAM-DATE-TIME:2022-10-27T17:59:29.957457Z
#EXTINF:2.090,
seg4967.ts
I believe #EXT-X-DISCONTINUITY should be on seg4967.ts and not seg4966.ts (yes I know if this is last segment for VOD you simple can't write it)
seg4965.ts
# Splice Point @ 10455.186122
#Iframe @ 10455.186122
#EXT-X-PROGRAM-DATE-TIME:2022-10-27T17:59:27.637347Z
#EXT-X-SCTE35:CUE="/DAqAAAAAAAAAP/wDwUAAAGPf0/+OBO5wQACAAAACgAIQ1VFSQAAAADsueIZ" ,CUE-IN=YES
#EXTINF:2.043,
seg4966.ts
#Iframe @ 10457.4849
#EXT-X-DISCONTINUITY
#EXT-X-PROGRAM-DATE-TIME:2022-10-27T17:59:29.957457Z
#EXTINF:2.090,
seg4967.ts
from x9k3.
Related Issues (20)
- Do You Like The Current Output of X9K3? Do You Have A Better Idea? HOT 18
- Problematically its not working HOT 10
- How to merge multiple ts input into one output? HOT 3
- Jerks in HLS when coverted from UDP. HOT 40
- error while coverting udp to hls HOT 4
- insert every 10 minutes HOT 4
- When can we expect abr ? HOT 2
- negative EXTINF values and no X_CUE tags from scte35 mpegts stream HOT 8
- SCTE-OUT/IN pairs inside EXT-X-DATERANGE do not have the same ID, as the standard says HOT 4
- Replay mode , not looping the video HOT 6
- New: Option to not to use EXT-X-DISCONTINUITY in SCTE35 marks HOT 12
- New: --replay should not include -c by default HOT 3
- Play on native player breaks in replay mode after restarting the loop HOT 11
- stdin input is not working
- Not inserting cue markers. HOT 23
- paypal account HOT 5
- Can't make sidecar pts and cue to working as expected HOT 10
- How to use in hls? HOT 4
- Transmission dropping HOT 22
- Input with multiple resolutions
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from x9k3.