Skip to content

Commit

Permalink
Secs -> Millis
Browse files Browse the repository at this point in the history
  • Loading branch information
rexim committed Dec 20, 2023
1 parent 0352133 commit 0e3a87b
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 48 deletions.
56 changes: 45 additions & 11 deletions lexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,34 +7,68 @@ import (
"strconv"
)

type Secs = float64
type Millis = int64

func tsToSecs(ts string) (Secs, error) {
// TODO: we really need more precise error reported for timestamp tokens.
// Like the diagnostics should point out at specific characters that are
// incorrect.

func parseSsAndMs(s string) (ss int64, ms Millis, err error) {
switch comps := strings.Split(s, "."); len(comps) {
case 2:
ss, err = strconv.ParseInt(comps[0], 10, 64);
if err != nil {
return
}
runes := []rune(comps[1])
ms = 0
for i := 0; i < 3; i += 1 {
ms = ms*10
if i < len(runes) {
ms += int64(runes[i] - '0')
}
}
return
case 1:
ss, err = strconv.ParseInt(comps[0], 10, 64);
if err != nil {
return
}
ms = 0
return
default:
err = fmt.Errorf("Unexpected amount of components in the seconds (%d): %s", len(comps), s)
return
}
}

func tsToMillis(ts string) (Millis, error) {
var err error = nil
var mm, hh int = 0, 0
var ss Secs = 0
var index = 0
var mm, hh, ss int64 = 0, 0, 0
var ms Millis = 0
index := 0
switch comps := strings.Split(ts, ":"); len(comps) {
case 3:
hh, err = strconv.Atoi(comps[index])
hh, err = strconv.ParseInt(comps[index], 10, 64)
if err != nil {
return 0, err
}
index += 1
fallthrough
case 2:
mm, err = strconv.Atoi(comps[index])
mm, err = strconv.ParseInt(comps[index], 10, 64)
if err != nil {
return 0, err
}
index += 1
fallthrough
case 1:
ss, err = strconv.ParseFloat(comps[index], 64)
ss, ms, err = parseSsAndMs(comps[index])
if err != nil {
return 0, err
}
return 60*60*Secs(hh) + 60*Secs(mm) + ss, nil

return 60*60*1000*Millis(hh) + 60*1000*Millis(mm) + Millis(ss)*1000 + ms, nil
default:
return 0, fmt.Errorf("Unexpected amount of components in the timestamp (%d)", len(comps))
}
Expand Down Expand Up @@ -133,7 +167,7 @@ var LiteralTokens = []LiteralToken{
type Token struct {
Kind TokenKind
Text []rune
Timestamp Secs
Timestamp Millis
Loc Loc
}

Expand Down Expand Up @@ -347,7 +381,7 @@ func (lexer *Lexer) ChopToken() (token Token, err error) {
}

token.Text = lexer.Content[begin:lexer.Cur]
token.Timestamp, err = tsToSecs(string(token.Text))
token.Timestamp, err = tsToMillis(string(token.Text))
if err != nil {
err = &DiagErr{
Loc: token.Loc,
Expand Down
64 changes: 27 additions & 37 deletions markut.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,28 @@ import (
"os"
"os/exec"
"path"
"strconv"
"strings"
"math"
"io/ioutil"
)

// TODO: Use fixed point numbers for Secs
// The resolution could depend on the FPS

// TODO: Make secsToTs accept float instead of int
func secsToTs(secs int) string {
hh := secs / 60 / 60
mm := secs / 60 % 60
ss := secs % 60
return fmt.Sprintf("%02d:%02d:%02d", hh, mm, ss)
func millisToTs(millis Millis) string {
hh := millis / 1000 / 60 / 60
mm := millis / 1000 / 60 % 60
ss := millis / 1000 % 60
ms := millis % 1000
return fmt.Sprintf("%02d:%02d:%02d.%03d", hh, mm, ss, ms)
}

type Chunk struct {
Start Secs
End Secs
Start Millis
End Millis
Name string
Loc Loc
InputPath string
Blur bool
Blur bool
}

func (chunk Chunk) Duration() Secs {
func (chunk Chunk) Duration() Millis {
return chunk.End - chunk.Start
}

Expand Down Expand Up @@ -66,7 +61,7 @@ func typeCheckArgs(loc Loc, argsStack []Token, signature ...TokenKind) (args []T

type Cut struct {
chunk int
pad Secs
pad Millis
}

type EvalContext struct {
Expand All @@ -85,18 +80,18 @@ type EvalContext struct {

func (context EvalContext) PrintSummary() {
fmt.Println("Cuts:")
secs := 0.0
var millis Millis = 0
for i, chunk := range context.chunks {
if i < len(context.chunks) - 1 {
fmt.Printf("%s: %s: %s\n", chunk.Loc, secsToTs(int(secs + chunk.Duration())), fmt.Sprintf("cut-%02d.mp4", i))
fmt.Printf("%s: %s: %s\n", chunk.Loc, millisToTs(millis + chunk.Duration()), fmt.Sprintf("cut-%02d.mp4", i))
}
secs += chunk.Duration()
millis += chunk.Duration()
}
fmt.Println()
fmt.Printf("Chunks Count: %d\n", len(context.chunks))
fmt.Printf("Cuts Count: %d\n", len(context.chunks) - 1)
fmt.Println()
fmt.Printf("Length: %s\n", secsToTs(int(secs)));
fmt.Printf("Length: %s\n", millisToTs(millis))
}

func evalMarkutFile(path string) (context EvalContext, ok bool) {
Expand Down Expand Up @@ -268,15 +263,6 @@ func evalMarkutFile(path string) (context EvalContext, ok bool) {
return
}
fmt.Printf("%s", string(args[0].Text));
case "putf":
args, err, argsStack = typeCheckArgs(token.Loc, argsStack, TokenTimestamp)
if err != nil {
fmt.Printf("%s: ERROR: type check failed for %s\n", token.Loc, command)
fmt.Printf("%s\n", err)
ok = false
return
}
fmt.Printf("%f", args[0].Timestamp);
case "putd":
args, err, argsStack = typeCheckArgs(token.Loc, argsStack, TokenTimestamp)
if err != nil {
Expand All @@ -294,7 +280,7 @@ func evalMarkutFile(path string) (context EvalContext, ok bool) {
ok = false
return
}
fmt.Printf("%s", secsToTs(int(args[0].Timestamp)));
fmt.Printf("%s", millisToTs(args[0].Timestamp));
case "here":
argsStack = append(argsStack, Token{
Loc: token.Loc,
Expand Down Expand Up @@ -325,7 +311,7 @@ func evalMarkutFile(path string) (context EvalContext, ok bool) {
argsStack = append(argsStack, Token{
Loc: token.Loc,
Kind: TokenTimestamp,
Timestamp: float64(n-1),
Timestamp: Millis(n-1),
})
case "chunk_duration":
n := len(context.chunks)
Expand Down Expand Up @@ -385,7 +371,7 @@ func evalMarkutFile(path string) (context EvalContext, ok bool) {
end := args[0]

if start.Timestamp > end.Timestamp {
fmt.Printf("%s: ERROR: the end of the chunk %s is earlier than its start %s\n", end.Loc, secsToTs(int(math.Floor(end.Timestamp))), secsToTs(int(math.Floor(start.Timestamp))));
fmt.Printf("%s: ERROR: the end of the chunk %s is earlier than its start %s\n", end.Loc, millisToTs(end.Timestamp), millisToTs(start.Timestamp));
fmt.Printf("%s: NOTE: the start is located here\n", start.Loc);
ok = false
return
Expand Down Expand Up @@ -447,6 +433,10 @@ func logCmd(name string, args ...string) {
fmt.Printf("[CMD] %s\n", strings.Join(chunks, " "))
}

func millisToSecsForFFmpeg(millis Millis) string {
return fmt.Sprintf("%d.%03d", millis/1000, millis%1000)
}

func ffmpegCutChunk(context EvalContext, chunk Chunk, y bool) error {
ffmpeg := ffmpegPathToBin()
args := []string{}
Expand All @@ -455,7 +445,7 @@ func ffmpegCutChunk(context EvalContext, chunk Chunk, y bool) error {
args = append(args, "-y")
}

args = append(args, "-ss", strconv.FormatFloat(chunk.Start, 'f', -1, 64))
args = append(args, "-ss", millisToSecsForFFmpeg(chunk.Start))
args = append(args, "-i", chunk.InputPath)

if len(context.VideoCodec) > 0 {
Expand All @@ -470,10 +460,10 @@ func ffmpegCutChunk(context EvalContext, chunk Chunk, y bool) error {
if len(context.AudioBitrate) > 0 {
args = append(args, "-ab", context.AudioBitrate)
}
args = append(args, "-t", strconv.FormatFloat(chunk.Duration(), 'f', -1, 64))
if chunk.Blur {
args = append(args, "-vf", "boxblur=50:5")
}
args = append(args, "-t", millisToSecsForFFmpeg(chunk.Duration()))
if chunk.Blur {
args = append(args, "-vf", "boxblur=50:5")
}
for _, outFlag := range context.ExtraOutFlags {
args = append(args, outFlag)
}
Expand Down

0 comments on commit 0e3a87b

Please sign in to comment.