mirror of
https://github.com/mpv-player/mpv.git
synced 2025-12-28 05:33:14 +00:00
command: add sub-start & sub-end properties
These properties contain the current subtitle's start and end times. Can be useful to cut sample audio through the scripting interface.
This commit is contained in:
@@ -1916,6 +1916,17 @@ Property list
|
|||||||
|
|
||||||
This property is experimental and might be removed in the future.
|
This property is experimental and might be removed in the future.
|
||||||
|
|
||||||
|
``sub-start``
|
||||||
|
Return the current subtitle start time (in seconds). If there's multiple
|
||||||
|
current subtitles, returns the first start time. If no current subtitle is
|
||||||
|
present null is returned instead.
|
||||||
|
|
||||||
|
``sub-end``
|
||||||
|
Return the current subtitle start time (in seconds). If there's multiple
|
||||||
|
current subtitles, return the last end time. If no current subtitle is
|
||||||
|
present, or if it's present but has unknown or incorrect duration, null
|
||||||
|
is returned instead.
|
||||||
|
|
||||||
``playlist-pos`` (RW)
|
``playlist-pos`` (RW)
|
||||||
Current position on playlist. The first entry is on position 0. Writing
|
Current position on playlist. The first entry is on position 0. Writing
|
||||||
to the property will restart playback at the written entry.
|
to the property will restart playback at the written entry.
|
||||||
|
|||||||
@@ -2845,6 +2845,38 @@ static int mp_property_sub_text(void *ctx, struct m_property *prop,
|
|||||||
return m_property_strdup_ro(action, arg, text);
|
return m_property_strdup_ro(action, arg, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct sd_times get_times(void *ctx, struct m_property *prop,
|
||||||
|
int action, void *arg)
|
||||||
|
{
|
||||||
|
struct sd_times res = { .start = MP_NOPTS_VALUE, .end = MP_NOPTS_VALUE };
|
||||||
|
MPContext *mpctx = ctx;
|
||||||
|
struct track *track = mpctx->current_track[0][STREAM_SUB];
|
||||||
|
struct dec_sub *sub = track ? track->d_sub : NULL;
|
||||||
|
double pts = mpctx->playback_pts;
|
||||||
|
if (!sub || pts == MP_NOPTS_VALUE)
|
||||||
|
return res;
|
||||||
|
return sub_get_times(sub, pts);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mp_property_sub_start(void *ctx, struct m_property *prop,
|
||||||
|
int action, void *arg)
|
||||||
|
{
|
||||||
|
double start = get_times(ctx, prop, action, arg).start;
|
||||||
|
if (start == MP_NOPTS_VALUE)
|
||||||
|
return M_PROPERTY_UNAVAILABLE;
|
||||||
|
return m_property_double_ro(action, arg, start);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int mp_property_sub_end(void *ctx, struct m_property *prop,
|
||||||
|
int action, void *arg)
|
||||||
|
{
|
||||||
|
double end = get_times(ctx, prop, action, arg).end;
|
||||||
|
if (end == MP_NOPTS_VALUE)
|
||||||
|
return M_PROPERTY_UNAVAILABLE;
|
||||||
|
return m_property_double_ro(action, arg, end);
|
||||||
|
}
|
||||||
|
|
||||||
static int mp_property_cursor_autohide(void *ctx, struct m_property *prop,
|
static int mp_property_cursor_autohide(void *ctx, struct m_property *prop,
|
||||||
int action, void *arg)
|
int action, void *arg)
|
||||||
{
|
{
|
||||||
@@ -3548,6 +3580,8 @@ static const struct m_property mp_properties_base[] = {
|
|||||||
{"sub-speed", mp_property_sub_speed},
|
{"sub-speed", mp_property_sub_speed},
|
||||||
{"sub-pos", mp_property_sub_pos},
|
{"sub-pos", mp_property_sub_pos},
|
||||||
{"sub-text", mp_property_sub_text},
|
{"sub-text", mp_property_sub_text},
|
||||||
|
{"sub-start", mp_property_sub_start},
|
||||||
|
{"sub-end", mp_property_sub_end},
|
||||||
|
|
||||||
{"vf", mp_property_vf},
|
{"vf", mp_property_vf},
|
||||||
{"af", mp_property_af},
|
{"af", mp_property_af},
|
||||||
|
|||||||
@@ -372,6 +372,23 @@ char *sub_get_text(struct dec_sub *sub, double pts)
|
|||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct sd_times sub_get_times(struct dec_sub *sub, double pts)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&sub->lock);
|
||||||
|
struct sd_times res = { .start = MP_NOPTS_VALUE, .end = MP_NOPTS_VALUE };
|
||||||
|
|
||||||
|
pts = pts_to_subtitle(sub, pts);
|
||||||
|
|
||||||
|
sub->last_vo_pts = pts;
|
||||||
|
update_segment(sub);
|
||||||
|
|
||||||
|
if (sub->sd->driver->get_times)
|
||||||
|
res = sub->sd->driver->get_times(sub->sd, pts);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&sub->lock);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
void sub_reset(struct dec_sub *sub)
|
void sub_reset(struct dec_sub *sub)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&sub->lock);
|
pthread_mutex_lock(&sub->lock);
|
||||||
|
|||||||
@@ -21,6 +21,11 @@ enum sd_ctrl {
|
|||||||
SD_CTRL_SET_VIDEO_DEF_FPS,
|
SD_CTRL_SET_VIDEO_DEF_FPS,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct sd_times {
|
||||||
|
double start;
|
||||||
|
double end;
|
||||||
|
};
|
||||||
|
|
||||||
struct attachment_list {
|
struct attachment_list {
|
||||||
struct demux_attachment *entries;
|
struct demux_attachment *entries;
|
||||||
int num_entries;
|
int num_entries;
|
||||||
@@ -38,6 +43,7 @@ bool sub_read_packets(struct dec_sub *sub, double video_pts);
|
|||||||
void sub_get_bitmaps(struct dec_sub *sub, struct mp_osd_res dim, int format,
|
void sub_get_bitmaps(struct dec_sub *sub, struct mp_osd_res dim, int format,
|
||||||
double pts, struct sub_bitmaps *res);
|
double pts, struct sub_bitmaps *res);
|
||||||
char *sub_get_text(struct dec_sub *sub, double pts);
|
char *sub_get_text(struct dec_sub *sub, double pts);
|
||||||
|
struct sd_times sub_get_times(struct dec_sub *sub, double pts);
|
||||||
void sub_reset(struct dec_sub *sub);
|
void sub_reset(struct dec_sub *sub);
|
||||||
void sub_select(struct dec_sub *sub, bool selected);
|
void sub_select(struct dec_sub *sub, bool selected);
|
||||||
void sub_update_opts(struct dec_sub *sub);
|
void sub_update_opts(struct dec_sub *sub);
|
||||||
|
|||||||
1
sub/sd.h
1
sub/sd.h
@@ -40,6 +40,7 @@ struct sd_functions {
|
|||||||
void (*get_bitmaps)(struct sd *sd, struct mp_osd_res dim, int format,
|
void (*get_bitmaps)(struct sd *sd, struct mp_osd_res dim, int format,
|
||||||
double pts, struct sub_bitmaps *res);
|
double pts, struct sub_bitmaps *res);
|
||||||
char *(*get_text)(struct sd *sd, double pts);
|
char *(*get_text)(struct sd *sd, double pts);
|
||||||
|
struct sd_times (*get_times)(struct sd *sd, double pts);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct lavc_conv;
|
struct lavc_conv;
|
||||||
|
|||||||
30
sub/sd_ass.c
30
sub/sd_ass.c
@@ -593,6 +593,35 @@ static char *get_text(struct sd *sd, double pts)
|
|||||||
return ctx->last_text;
|
return ctx->last_text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct sd_times get_times(struct sd *sd, double pts)
|
||||||
|
{
|
||||||
|
struct sd_ass_priv *ctx = sd->priv;
|
||||||
|
ASS_Track *track = ctx->ass_track;
|
||||||
|
struct sd_times res = { .start = MP_NOPTS_VALUE, .end = MP_NOPTS_VALUE };
|
||||||
|
|
||||||
|
if (pts == MP_NOPTS_VALUE || ctx->duration_unknown)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
long long ipts = find_timestamp(sd, pts);
|
||||||
|
|
||||||
|
for (int i = 0; i < track->n_events; ++i) {
|
||||||
|
ASS_Event *event = track->events + i;
|
||||||
|
if (ipts >= event->Start && ipts < event->Start + event->Duration) {
|
||||||
|
double start = event->Start / 1000.0;
|
||||||
|
double end = event->Duration == UNKNOWN_DURATION ?
|
||||||
|
MP_NOPTS_VALUE : (event->Start + event->Duration) / 1000.0;
|
||||||
|
|
||||||
|
if (res.start == MP_NOPTS_VALUE || res.start > start)
|
||||||
|
res.start = start;
|
||||||
|
|
||||||
|
if (res.end == MP_NOPTS_VALUE || res.end < end)
|
||||||
|
res.end = end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
static void fill_plaintext(struct sd *sd, double pts)
|
static void fill_plaintext(struct sd *sd, double pts)
|
||||||
{
|
{
|
||||||
struct sd_ass_priv *ctx = sd->priv;
|
struct sd_ass_priv *ctx = sd->priv;
|
||||||
@@ -687,6 +716,7 @@ const struct sd_functions sd_ass = {
|
|||||||
.decode = decode,
|
.decode = decode,
|
||||||
.get_bitmaps = get_bitmaps,
|
.get_bitmaps = get_bitmaps,
|
||||||
.get_text = get_text,
|
.get_text = get_text,
|
||||||
|
.get_times = get_times,
|
||||||
.control = control,
|
.control = control,
|
||||||
.reset = reset,
|
.reset = reset,
|
||||||
.select = enable_output,
|
.select = enable_output,
|
||||||
|
|||||||
@@ -383,14 +383,8 @@ static void decode(struct sd *sd, struct demux_packet *packet)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void get_bitmaps(struct sd *sd, struct mp_osd_res d, int format,
|
static struct sub *get_current(struct sd_lavc_priv *priv, double pts)
|
||||||
double pts, struct sub_bitmaps *res)
|
|
||||||
{
|
{
|
||||||
struct sd_lavc_priv *priv = sd->priv;
|
|
||||||
struct mp_subtitle_opts *opts = sd->opts;
|
|
||||||
|
|
||||||
priv->current_pts = pts;
|
|
||||||
|
|
||||||
struct sub *current = NULL;
|
struct sub *current = NULL;
|
||||||
for (int n = 0; n < MAX_QUEUE; n++) {
|
for (int n = 0; n < MAX_QUEUE; n++) {
|
||||||
struct sub *sub = &priv->subs[n];
|
struct sub *sub = &priv->subs[n];
|
||||||
@@ -407,6 +401,19 @@ static void get_bitmaps(struct sd *sd, struct mp_osd_res d, int format,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void get_bitmaps(struct sd *sd, struct mp_osd_res d, int format,
|
||||||
|
double pts, struct sub_bitmaps *res)
|
||||||
|
{
|
||||||
|
struct sd_lavc_priv *priv = sd->priv;
|
||||||
|
struct mp_subtitle_opts *opts = sd->opts;
|
||||||
|
|
||||||
|
priv->current_pts = pts;
|
||||||
|
|
||||||
|
struct sub *current = get_current(priv, pts);
|
||||||
|
|
||||||
if (!current)
|
if (!current)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -483,6 +490,25 @@ static void get_bitmaps(struct sd *sd, struct mp_osd_res d, int format,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct sd_times get_times(struct sd *sd, double pts)
|
||||||
|
{
|
||||||
|
struct sd_lavc_priv *priv = sd->priv;
|
||||||
|
struct sd_times res = { .start = MP_NOPTS_VALUE, .end = MP_NOPTS_VALUE };
|
||||||
|
|
||||||
|
if (pts == MP_NOPTS_VALUE)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
struct sub *current = get_current(priv, pts);
|
||||||
|
|
||||||
|
if (!current)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
res.start = current->pts;
|
||||||
|
res.end = current->endpts;
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
static bool accepts_packet(struct sd *sd, double min_pts)
|
static bool accepts_packet(struct sd *sd, double min_pts)
|
||||||
{
|
{
|
||||||
struct sd_lavc_priv *priv = sd->priv;
|
struct sd_lavc_priv *priv = sd->priv;
|
||||||
@@ -622,6 +648,7 @@ const struct sd_functions sd_lavc = {
|
|||||||
.init = init,
|
.init = init,
|
||||||
.decode = decode,
|
.decode = decode,
|
||||||
.get_bitmaps = get_bitmaps,
|
.get_bitmaps = get_bitmaps,
|
||||||
|
.get_times = get_times,
|
||||||
.accepts_packet = accepts_packet,
|
.accepts_packet = accepts_packet,
|
||||||
.control = control,
|
.control = control,
|
||||||
.reset = reset,
|
.reset = reset,
|
||||||
|
|||||||
7
test/subtimes.js
Normal file
7
test/subtimes.js
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
function subtimes() {
|
||||||
|
mp.msg.info("sub-start: " + mp.get_property_number("sub-start"));
|
||||||
|
mp.msg.info("sub-end: " + mp.get_property_number("sub-end"));
|
||||||
|
mp.msg.info("sub-text: " + mp.get_property_native("sub-text"));
|
||||||
|
}
|
||||||
|
|
||||||
|
mp.add_key_binding("t", "subtimes", subtimes);
|
||||||
Reference in New Issue
Block a user