Coder Social home page Coder Social logo

barasher / go-exiftool Goto Github PK

View Code? Open in Web Editor NEW
226.0 226.0 41.0 216 KB

Golang wrapper for Exiftool : extract as much metadata as possible (EXIF, ...) from files (pictures, pdf, office documents, ...)

License: GNU General Public License v3.0

Go 100.00%
exif exiftool golang iptc wrapper-api

go-exiftool's People

Contributors

agorman avatar barasher avatar blesmol avatar dhui avatar ghyman1 avatar hexoplon avatar kjeldgaard avatar proger4ever avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

go-exiftool's Issues

Custom extraInitArgs

Would you be open to a pull request that allowed a user of the module to set their own extraInitArgs? Something like:

func Args(args ...string) func(*Exiftool) error {
	return func(e *Exiftool) error {
		e.extraInitArgs = append(e.extraInitArgs, args...)
		return nil
	}
}

That way a user that knows what they're doing could put any fields they want. For example if I wanted to get the Orientation tag as a number.

et, err := exiftool.NewExiftool(
	exiftool.Args("-Orientation#"),
)

init new instance

hi
pls help
how can I init a new instance exiftool with a arg "-a" ?
exapmle:
et, err := exiftool.NewExiftool("-a")

$exiftool -a /path/file

Fix error details when marshalling error

When a marshalling error happens:

error during unmarshaling ([32 32 32 32 49 32 100 105 114 101 99 116 111 114 105 101 115 32 115 99 97 110 110 101 100 10 32 32 32 32 48 32 105 109 97 103 101 32 102 105 108 101 115 32 114 101 97 100 10]): invalid character 'd' after top-level value)

The error should be more "human readable"

Filename including Non-ASCII character isn't supported in Windows

I try to use go-exiftool to get exif from the JPEG file in Windows environment.

When I call ExtractMetadata(), if the parameter files includes non-ASCII character, for example,
fileInfos := et.ExtractMetadata("D:\\测试数据\\IMG_20220102_202220.jpg")
the calling is failed, with the error message like

failed: failed to parse exif data: error during unmarshaling (Error: File not found - D:/测试数据/IMG_20220102_202220.jpg
): invalid character 'E' looking for beginning of value)

But if the parameter files includes only ASCII character, for example,
fileInfos := et.ExtractMetadata("D:\\test-data\\IMG_20220102_202220.jpg")
everything is OK.

And I found this page [https://exiftool.org/exiftool_pod.html#WINDOWS-UNICODE-FILE-NAMES] in exiftool documentation. So, I think maybe go-exiftool should add the option -charset filename=utf8 to solve the problem.

I try to change the code of go-exiftool. In detail, I change
var initArgs = []string{"-stay_open", "True", "-@", "-"}
to
var initArgs = []string{"-charset", "filename=utf8", "-stay_open", "True", "-@", "-"}
And it's really worked in Windows. But I'm not sure if it has side effect in other OS. I'll create a pull request soon.

Supply custom extraInitArgs

This is probably less of an issue, and more of me being a go noob, so please excuse the ask but I've been running myself in circles and hoping you can help me out.

I want to pass the '-ee' flag to exiftool. I have some files that the date I am looking for only shows with the -ee flag. Bellow is my call to NewExifTool. I get:

s.extraInitArgs undefined (type *exiftool.Exiftool has no field or method extraInitArgs)

Am I doing something wrong, or is this just not an option with go-exiftool?

	et, err := exiftool.NewExiftool(func(s *exiftool.Exiftool) error {
		s.extraInitArgs = append(s.extraInitArgs, "-ee")
		return nil
		})
	if err != nil {
		fmt.Printf("Error initializing %v\n", err)
	}

Error when scanning files with special chars in filename

Hi,

I'm currently using go-exiftool on windows, and everything is working fine so far, except when trying to call ExtractMetadata() on files where the path includes special characters, e.g. foö.jpg.

error during unmarshaling (Error: File not found - test/foö.jpg
): invalid character 'E' looking for beginning of value)

The same works fine when using exiftool.pl directly on the command line. Not sure whether that problem is limited to windows or would also appear on Mac or Linux...

Best regards,
Philipp

Deadlock when exiftool process is killed before parent

There is a deadlock in the code if the exiftool process is killed before the parent process calls Close(). The deadlock occurs here https://github.com/barasher/go-exiftool/blob/master/exiftool.go#L183. It happens because r and w created in NewExiftool are never closed.

This can happen pretty often when the parent program is killed using with CTRL+c. By default on Linux exiftool is run in the same process group which causes the signal to reach the exiftool process before the parent has the time to close it cleanly.

One possible solution would be to run exiftool in it's own process group so signals to the parent aren't passed to the child. The problem with this is that the way process groups are handled is OS dependent and code would need to be added to handle different operating systems. Another problem is that it's desirable to make sure exiftool is closed even when people aren't properly calling Close in their code.

Anther possible solution would be to add a goroutine in the NewExiftool after cmd.Start() that can close r and w when the process exits.

go func() {
	e.cmd.Wait()
	r.Close()
	w.Close()
}()

Here is a minimal failing case https://gist.github.com/agorman/6ef72d4be151326e39de980247c6ea46. To reproduce it run it against a directory with a bunch of images and do a CTRL+c or kill the exiftool process.

I'm happy to write a pull request but wanted to get your input on possible solutions before doing that.

Thanks!

ExtractMetadata becomes non-responsive after individual error

Hi, thanks for sharing this package. I ran into an error case trying to do a filepath.Walk over my photos directory. Manually skipping directories does avoid this issue, but it seems like the wrong behavior for ExtractMetadata to silently start giving incorrect results as a result of a previous call. I'd like to incorporate this package into some of my workflows, so I'm raising the issue to help improve the package's usability/reliability. Here is a test that reproduces the behavior:

func TestNonResponsiveExiftool(t *testing.T) {
	t.Parallel()

	// create test directory with about 200MB worth of photos
	// 10,000 of the included jpg or 6 30MB CR2's both repro
	dirPath := "./testdata/extractkiller"

	err := os.Mkdir(dirPath, 0744)
	require.NoError(t, err)
	defer os.RemoveAll(dirPath)

	for i:=0;i < 10_000;i++ {
		err := copyFile("./testdata/20190404_131804.jpg", path.Join(dirPath, fmt.Sprintf("%d.jpg", i)))
		require.NoError(t, err)
	}


	// initialize exiftool
	e, err := NewExiftool(Debug())
	require.NoError(t, err)
	defer e.Close()


	// control case, everything working normally
	f := e.ExtractMetadata("./testdata/20190404_131804.jpg")
	assert.Equal(t, 1, len(f))
	assert.NoError(t, f[0].Err)

	// case that breaks the session, reading a directory does not seem to be supported by this package, which is okay, and I would expect it to throw an error in that case, but it should not make future reads invalid.
	f = e.ExtractMetadata(dirPath)
	assert.Error(t, f[0].Err)

	// control case no longer works
	f = e.ExtractMetadata("./testdata/20190404_131804.jpg")
	assert.Equal(t, 1, len(f))
	assert.NoError(t, f[0].Err)

}

I suspect the issue is either a race (scanning output before it's finished), or improper buffer usage (overflow maybe?). I ran the same test with exiftool directly and got output right away without issue.

One other note, it looks like exiftool supports paths to a directory as an input, or even a list of multiple files. It might be worth reworking the design to let exiftool handle the work of managing multiple paths (directories or files), and add support for parsing the multi-file output.

I'll try to work on a PR for this, but posting the issue now as a heads up, and to see if you have any suggestions on the right design to fix the issue.

Binary data extraction

ExtractAllBinaryMetadata option extracts binary metadata among other metadata. Exiftool encode binary values using base64, which is not optimized when you're only interested in the binary fileds.

The idea is to add a tool that extracts binary metadata directly as []byte instead of base64 string.

About stay_open using multiprocessing

If I have []byte data from internet and now I have to save it a file and then call ExtractMetadataInfo(filename).
Does the stay_open pattern support input []byte data?
Such as
func ExtractMetadataInfo(data []byte)(rst FileMetadata,err error){ }

How to use it on Windows?

I have put the 'exiftool.exe' in %PATH%, but it still got 'Error when intializing: error when executing commande: exec: "exiftool": executable file not found in %PATH%'

Add setter to FileMetadata

Add setter to FileMetadata

  • func (fm FileMetadata) SetFloat(k string, v float64)
  • func (fm FileMetadata) SetInt(k string, v int64)
  • func (fm FileMetadata) SetString(k string, v string)
  • func (fm FileMetadata) SetStrings(k string, v ...string)

Sorting of Exif parameters

Hi,

first of all, I want to thank you for making it possible to use exiftool in Go. I tryed it out, and it works well, but I have different order of parameters if I compare the order of parameters that I get from exiftool, if I executed it in the terminal.
Do you have any idea, how I get the same order of parameters as from exiftool?

Best regards,

Dorothea

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.