Skip to content

Commit

Permalink
Merge pull request #12 from GanymedeNil/feature/v2.1
Browse files Browse the repository at this point in the history
Feature/v2.1
  • Loading branch information
GanymedeNil authored Nov 7, 2020
2 parents c7b21c0 + d95c34d commit f3ff4e8
Show file tree
Hide file tree
Showing 23 changed files with 747 additions and 262 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ srt 字幕文件转为final cut pro 字幕文件(fcpxml)
```bash
$ ./srt2fcpxml
-fd int
帧率目前只支持整数24、25、30、50、60 (default 25)
帧率目前支持 23.98、24、25、29.97、30、50、59.94、60 (default 25)
-srt string
srt 字幕文件
```
Expand Down
12 changes: 10 additions & 2 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,23 @@ import (
"os"
"path/filepath"
"srt2fcpxml/core"
"strconv"
"strings"

"github.com/asticode/go-astisub"
)

func main() {
srtFile := flag.String("srt", "", "srt 字幕文件")
frameDuration := flag.Int("fd", 25, "帧率目前只支持整数24、25、30、50、60")
frameDurationPoint := flag.String("fd", "25", "帧率目前支持 23.98、24、25、29.97、30、50、59.94、60")
flag.Parse()
var frameDuration interface{}
if len(*frameDurationPoint) > 2 {
frameDuration, _ = strconv.ParseFloat(*frameDurationPoint, 64)
} else {
frameDuration, _ = strconv.Atoi(*frameDurationPoint)
}

f, _ := astisub.OpenFile(*srtFile)
out := `<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE fcpxml>
Expand All @@ -26,7 +34,7 @@ func main() {
}

project, path := getPath(*srtFile)
result, _ := core.Srt2FcpxmlExport(project, *frameDuration, f)
result, _ := core.Srt2FcpXmlExport(project, frameDuration, f)
out += string(result)
targetFile := fmt.Sprintf("%s/%s.fcpxml", path, project)
fd, err := os.Create(targetFile)
Expand Down
51 changes: 51 additions & 0 deletions core/FcpXML/Common/Frame.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package Common

import (
"errors"
"fmt"
"srt2fcpxml/lib"
)

func FrameMapString(frameRate interface{}) (string, error) {
switch v := frameRate.(type) {
case float64:
return fmt.Sprintf("%d/%d", 1001, int64(lib.Round(v, 0)*1000)), nil
case int:
return fmt.Sprintf("%d/%d", 100, v*100), nil
default:
return "", errors.New("frameRate is int or float")
}
}

func FrameMap(frameRate interface{}) (float64, error) {
switch v := frameRate.(type) {
case float64:
return 1001 / (lib.Round(v, 0) * 1000), nil
case int:
return 100 / float64(v*100), nil
default:
return 0, errors.New("frameRate is int or float")
}
}

func FrameDuration(frameRate interface{}) float64 {
switch v := frameRate.(type) {
case float64:
return v
case int:
return float64(v)
default:
return 0
}
}

func FrameDurationFormat(frameRate interface{}) (float64, float64, error) {
switch v := frameRate.(type) {
case float64:
return 1001, lib.Round(v, 0) * 1000, nil
case int:
return 100, float64(v * 100), nil
default:
return 0, 0, errors.New("frameRate is int or float")
}
}
93 changes: 93 additions & 0 deletions core/FcpXML/Common/Frame_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package Common

import (
"log"
"srt2fcpxml/lib"
"testing"
)

func TestFrameMap(t *testing.T) {
type args struct {
frameRate interface{}
}
tests := []struct {
name string
args args
want float64
wantErr bool
}{
{
name: "23.98",
args: struct{ frameRate interface{} }{frameRate: 23.98},
want: 1001 / float64(24000),
wantErr: false,
},
{
name: "24",
args: struct{ frameRate interface{} }{frameRate: 24},
want: 100 / float64(2400),
wantErr: false,
},
{
name: "err",
args: struct{ frameRate interface{} }{frameRate: "ad"},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := FrameMap(tt.args.frameRate)
if (err != nil) != tt.wantErr {
t.Errorf("FrameMap() error = %v, wantErr %v", err, tt.wantErr)
return
}
f := lib.Floater{Accuracy: 0.000000000001}
log.Print(got)
log.Print(tt.want)
if !f.IsEqual(got, tt.want) {
t.Errorf("FrameMap() got = %v, want %v", got, tt.want)
}
})
}
}

func TestFrameMapString(t *testing.T) {
type args struct {
frameRate interface{}
}
tests := []struct {
name string
args args
want string
wantErr bool
}{
{
name: "23.98",
args: struct{ frameRate interface{} }{frameRate: 23.98},
want: "1001/24000",
},
{
name: "24",
args: struct{ frameRate interface{} }{frameRate: 24},
want: "100/2400",
wantErr: false,
},
{
name: "err",
args: struct{ frameRate interface{} }{frameRate: "ad"},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := FrameMapString(tt.args.frameRate)
if (err != nil) != tt.wantErr {
t.Errorf("FrameMapString() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want {
t.Errorf("FrameMapString() got = %v, want %v", got, tt.want)
}
})
}
}
41 changes: 41 additions & 0 deletions core/FcpXML/FcpXML.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package FcpXML

import (
"encoding/xml"
"srt2fcpxml/core/FcpXML/Library"
"srt2fcpxml/core/FcpXML/Resources"
)

type FcpXML struct {
XMLName xml.Name `xml:"fcpxml"`
Text string `xml:",chardata"`
Version string `xml:"version,attr"`
Resources *Resources.Resources `xml:"resources"`
Library *Library.Library `xml:"library"`
}

func New() *FcpXML {
return &FcpXML{
XMLName: xml.Name{},
Text: "",
Version: "1.7",
Resources: &Resources.Resources{},
Library: &Library.Library{},
}
}

func (fcp *FcpXML) SetVersion(version string) *FcpXML {
fcp.Version = version
return fcp
}

func (fcp *FcpXML) SetResources(resources *Resources.Resources) *FcpXML {
fcp.Resources = resources
return fcp
}

func (fcp *FcpXML) SetLibrary(library *Library.Library) *FcpXML {
fcp.Library = library
return fcp

}
51 changes: 51 additions & 0 deletions core/FcpXML/FcpXML_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package FcpXML

import (
"encoding/xml"
"srt2fcpxml/core/FcpXML/Library"
"srt2fcpxml/core/FcpXML/Library/Event"
"srt2fcpxml/core/FcpXML/Library/Event/Project"
"srt2fcpxml/core/FcpXML/Library/Event/Project/Sequence"
"srt2fcpxml/core/FcpXML/Library/Event/Project/Sequence/Spine"
"srt2fcpxml/core/FcpXML/Library/Event/Project/Sequence/Spine/Gap"
"srt2fcpxml/core/FcpXML/Library/Event/Project/Sequence/Spine/Gap/Title"
"srt2fcpxml/core/FcpXML/Resources"
"testing"
)

func TestFcpXML_SetVersion(t *testing.T) {
fcpxml := New()
res := Resources.NewResources()
res.SetEffect(Resources.NewEffect())
format := Resources.NewFormat().
SetWidth(1440).
SetHeight(1080).
SetFrameRate(23.98).Render()
res.SetFormat(format)
fcpxml.SetResources(res)

gap := Gap.NewGap(180.2)

textStyleDef := Title.NewTextStyleDef(1)
text := Title.NewContent(1, "4:00")
title := Title.NewTitle("4:00 - 基本字幕", 4.0, 7.8).SetTextStyleDef(textStyleDef).SetText(text)
title.AddParam(Title.NewParams("位置", "9999/999166631/999166633/1/100/101", "0 -450"))
title.AddParam(Title.NewParams("对齐", "9999/999166631/999166633/2/354/999169573/401", "1 (居中)"))
title.AddParam(Title.NewParams("展平", "9999/999166631/999166633/2/351", "1"))
gap.AddTitle(title)

spine := Spine.NewSpine().SetGap(gap)

seq := Sequence.NewSequence(180.2).SetSpine(spine)

project := Project.NewProject("ceshi").SetSequence(seq)

event := Event.NewEvent().SetProject(project)

lib := Library.NewLibrary("未命名 1").SetEvent(event)

fcpxml.SetLibrary(lib)

e, _ := xml.MarshalIndent(&fcpxml, "", " ")
t.Log(string(e))
}
28 changes: 28 additions & 0 deletions core/FcpXML/Library/Event/Event.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package Event

import (
"srt2fcpxml/core/FcpXML/Library/Event/Project"
"time"

uuid "github.com/satori/go.uuid"
)

type Event struct {
Text string `xml:",chardata"`
Name string `xml:"name,attr"`
Uid string `xml:"uid,attr"`
Project *Project.Project `xml:"project"`
}

func NewEvent() *Event {
return &Event{
Name: time.Now().Format("2006-01-02"),
Uid: uuid.NewV4().String(),
Project: &Project.Project{},
}
}

func (e *Event) SetProject(project *Project.Project) *Event {
e.Project = project
return e
}
31 changes: 31 additions & 0 deletions core/FcpXML/Library/Event/Project/Project.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package Project

import (
"srt2fcpxml/core/FcpXML/Library/Event/Project/Sequence"
"time"

uuid "github.com/satori/go.uuid"
)

type Project struct {
Text string `xml:",chardata"`
Name string `xml:"name,attr"`
Uid string `xml:"uid,attr"`
ModDate string `xml:"modDate,attr"`
Sequence *Sequence.Sequence `xml:"sequence"`
}

func NewProject(projectName string) *Project {
modDate := time.Now().Format("2006-01-02 15:04:05 -0700")
return &Project{
Name: projectName,
Uid: uuid.NewV4().String(),
ModDate: modDate,
Sequence: &Sequence.Sequence{},
}
}

func (p *Project) SetSequence(sequence *Sequence.Sequence) *Project {
p.Sequence = sequence
return p
}
41 changes: 41 additions & 0 deletions core/FcpXML/Library/Event/Project/Sequence/Sequence.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package Sequence

import (
"fmt"
"srt2fcpxml/core/FcpXML/Common"
"srt2fcpxml/core/FcpXML/Library/Event/Project/Sequence/Spine"
"srt2fcpxml/core/FcpXML/Resources"
"srt2fcpxml/lib"
)

type Sequence struct {
Text string `xml:",chardata"`
Duration string `xml:"duration,attr"`
Format string `xml:"format,attr"`
TcStart string `xml:"tcStart,attr"`
TcFormat string `xml:"tcFormat,attr"`
AudioLayout string `xml:"audioLayout,attr"`
AudioRate string `xml:"audioRate,attr"`
Spine *Spine.Spine `xml:"spine"`
}

func NewSequence(duration float64) *Sequence {
frameRate := Resources.GetFrameRate()
frameRateR := Common.FrameDuration(frameRate)
frameDurationMolecular, frameDurationDenominator, _ := Common.FrameDurationFormat(frameRate)
return &Sequence{
Text: "",
Duration: fmt.Sprintf("%.f/%.fs", lib.Round(duration*frameRateR, 0)*frameDurationMolecular, frameDurationDenominator),
Format: "r1",
TcStart: "0s",
TcFormat: "NDF",
AudioLayout: "stereo",
AudioRate: "48k",
Spine: &Spine.Spine{},
}
}

func (s *Sequence) SetSpine(spine *Spine.Spine) *Sequence {
s.Spine = spine
return s
}
Loading

0 comments on commit f3ff4e8

Please sign in to comment.