···16161717 mp3chap file.mp3 0 "chapter 1 is great" 123 "chapter 2 is ok" 456 "chapter 3 is boring"
18181919-The first argument is the path to the MP3 file, then pairs of arguments each containing
2020-a start time in seconds, and the chapter title.
1919+The first argument is the path to the MP3 file, then pairs of arguments each
2020+containing a start time in seconds, and the chapter title.
2121+2222+It is assumed that each chapter ends where the next one begins, and that the
2323+final chapter ends at the last millisecond of the file (as defined in its
2424+`TLEN` ID3 frame).
2525+2626+If the file does not contain a `TLEN` ID3 frame, a final time argument must
2727+be supplied (in seconds) which will be used as the end time of the final
2828+chapter.
21292222-It is assumed that each chapter ends where the next one begins, and that the final chapter
2323-ends at the last millisecond of the file (as defined in its `TLEN` ID3 frame).
3030+ mp3chap file.mp3 0 "chapter 1 is great" 123 "chapter 2 is ok" 456 "chapter 3 is boring" 789
24312532Changes to the ID3 tag in the MP3 file are written out in-place.
2633
+29-15
mp3chap.go
···62626363 chaps := make([]Chapter, 0)
6464 tocchaps := make([]string, 0)
6565+ finalEnd := uint64(0)
65666666- for x := 2; x < len(os.Args)-1; x += 2 {
6767+ x := 2
6868+ for ; x < len(os.Args)-1; x += 2 {
6769 if x+1 > len(os.Args)-2+1 {
6870 usage()
6971 }
···8082 chaps = append(chaps, chap)
8183 }
82848585+ // if there is a final odd arg, use it as the final chapter end
8686+ if x < len(os.Args) {
8787+ finalEnd, err = strconv.ParseUint(os.Args[x], 10, 32)
8888+ if err != nil {
8989+ log.Fatal("failed parsing final seconds %#v: %v", os.Args[x], err)
9090+ }
9191+ }
9292+8393 // each chapter ends where the next one starts
8494 for x := range chaps {
8595 if x < len(chaps)-1 {
···8797 }
8898 }
89999090- // and the last one ends when the file does
9191- tlenf := mp3.Frame("TLEN")
9292- if tlenf == nil {
9393- log.Fatal("can't find TLEN frame, don't know total duration")
9494- }
9595- tlenft, ok := tlenf.(*id3v2.TextFrame)
9696- if !ok {
9797- log.Fatal("can't convert TLEN to TextFrame")
9898- }
9999- tlen, err := strconv.ParseUint(tlenft.Text(), 10, 32)
100100- if err == nil {
101101- log.Fatal("can't parse TLEN value %#v\n", tlenft.Text())
102102- }
100100+ if finalEnd == 0 {
101101+ // and the last one ends when the file does
102102+ tlenf := mp3.Frame("TLEN")
103103+ if tlenf == nil {
104104+ log.Fatal("can't find TLEN frame, don't know total duration")
105105+ }
106106+ tlenft, ok := tlenf.(*id3v2.TextFrame)
107107+ if !ok {
108108+ log.Fatal("can't convert TLEN to TextFrame")
109109+ }
110110+ tlen, err := strconv.ParseUint(tlenft.Text(), 10, 32)
111111+ if err == nil {
112112+ log.Fatal("can't parse TLEN value %#v\n", tlenft.Text())
113113+ }
103114104104- chaps[len(chaps)-1].endSecs = uint32(tlen)
115115+ chaps[len(chaps)-1].endSecs = uint32(tlen)
116116+ } else {
117117+ chaps[len(chaps)-1].endSecs = uint32(finalEnd)
118118+ }
105119106120 // ready to modify the file, clear out what's there
107121 mp3.DeleteFrames("CTOC")